#!/usr/bin/awk -f
# arrays of arrays are support only after gawk v4.0
# arguments: m for module count, o for subobj count, d for debugging, f for the mapfile, t for segment(.text .rodata .data).
# m: [0, 50], module count, can control the number of output primary goals(*.a/*.o).
# o: if (m=0); then o=0;elif (m>0); then o=[0, 30]; fi,subobj count,can control the number of output secondary goals(*.o).
# d: 0 or 1, control whether to printout Debugging Accumulation info.
# f: mapfile to be processed.
# t: ".text" ".rodata" ".data", segment type

BEGIN {
	# Array element's sorted by value in descending order
	PROCINFO["sorted_in"] = "@val_num_desc"
	# Additional module
	moduleName["linker"] = "linker"
}

#1 extract loaded module name as in the leaf folder path
#moduleName[module]=module=the module name
/^LOAD/ {
	match($2, /\/[^\/]*\.[^\/]*$/)
	module = substr($2, RSTART+1)
	if (!moduleName[module]){
		moduleName[module] = module
		#print "module="module "    moduleName["module"]="moduleName[module]
	}
}

#2 extrac the .text, .rodata and .data totalsize the beginning of each interested section
/^\..*0x.*0x/ {
	if ($1 == ".text" || $1 == ".rodata" || $1 == ".data" || $1 == ".rom"){
		section = $1
		sectionSize[$1] = strtonum($3)
		#print "section="section "     sectionSize["section"]="sectionSize[$1]
	}
	else{
		section = ""
	}
	next
}

#3 accumulate module(*.a/*.o) size and subobj(*.o) size in each interested section
section && $0 ~ /.*[[:blank:]]0x.*[[:blank:]]0x/ {
	#print $0
	#3.1 filter valid rows
	if (((NF == 4  && $1 ~ /^\./) || (NF == 3  && $1 ~ /^0x/ && strtonum($1) > 0)) && $0 !~ /.*\.mod\.o$/) {
		#print $0
		match($NF, /\/[^\/]*\.[^\/\(]*\(/)
		#3.2 separater primary and secondary goals by filtering
		if (RSTART){
			#3.3 separater secondary goals
			#print $0
			curModule = substr($NF, RSTART+1, RLENGTH-2)

			match($NF, /\([^\(]*\.[^\(]*\)/)
			curSubObj = substr($NF, RSTART+1, RLENGTH-2)
			curSize = $(NF-1)

			#printf("%-30s%-50s%-26s\n", sprintf("curModule=%s", curModule), sprintf("curSubObj=%s", curSubObj), sprintf("curSize=%s", curSize))
		}
		else{
			#print $0
			#3.4 separater primary goals
			match($NF, /\/[^\/]*\.[^\/\(]*$/)
			#print "NF="$NF"   RSTART="RSTART

			if (RSTART) {
				curModule = substr($NF, RSTART+1, RLENGTH-1)
				curSize = $(NF-1)

				#printf("%-60s%-26s\n", sprintf("curModule=%s", curModule), sprintf("curSize=%s", curSize))
			}
			else{
				curModule = $NF
				curSize = $(NF-1)
				#print "section="section "    curModule="curModule  "    curSize="curSize
			}
			curSubObj = ""
		}

		#3.5 use curModule curSubObj curSize to calculate the size of each primary and secondary goals, and store them in arrays
		#if (moduleName[curModule])
		if ( 1 )
		{
			accSize += strtonum(curSize)

			moduleSize[".total"][curModule] += strtonum(curSize)
			moduleSize[section][curModule] += strtonum(curSize)

			if (section == ".rodata") {
				textsize += strtonum(curSize)
			    #print "moduleSize["section"]["curModule"]="moduleSize[section][curModule] "    textsize="textsize
			}

			if (curSubObj){
				subObjSize[curModule][".total"][curSubObj] += strtonum(curSize)
				subObjSize[curModule][section][curSubObj] += strtonum(curSize)
				isContainObj[curModule] = 1
			}
			else {
				isContainObj[curModule] = 0
				#directObjSize[curModule][".total"] += strtonum(curSize)
				#directObjSize[curModule][section] += strtonum(curSize)
			}
		}
		else
		{
			printf("module:\"%s\" Not Exist!\n", module)
		}
	}
	else{
		#print $0
		#3.6 calculate size of *fill* line
		if ($1 == "*fill*") {
			moduleSize[section]["*fill*"] += strtonum($NF)
			#print "section="section "    "$0	"    "$NF
		}
		else {
			#printf("NF[%d]:\"%s\" invalid!\n", NF, $0)
		}
	}
}

END {
	#4.1 parse params: m, o, d, f, t
	# Module count to have break-down analysis
	if (m > 50)
		MODULECOUNT = 50
	else
		MODULECOUNT = m

	# Object counts in each interested module to have break-down analysis
	if (MODULECOUNT > 0) {
		if (o > 30)
			SUBOBJCOUNT = 30
		else
			SUBOBJCOUNT = o
	}
	else {
		SUBOBJCOUNT = 0
	}

	if ("X" != "X"f ) {
		SRCFILENAME = sprintf("THD_%s", f)
	}

	if (".text" == t || ".rodata" == t || ".data" == t) {
		SEGTYPE = t
	}

	# Code section @ ".rom" or ".text"
	if (sectionSize[".rom"])
		codeSection = ".rom"
	else
		codeSection = ".text"

	#print "MODULECOUNT="MODULECOUNT "    SUBOBJCOUNT="SUBOBJCOUNT "    d="d
	#4.2 printout summary info include .text .rodata .data and total size
	totalSize = sectionSize[codeSection] + sectionSize[".rodata"] + sectionSize[".data"]

	#printf("#####################################################################################################\n")
	#printf("%-36s%16s%16s%16s%16s\n", "Module", ".total", codeSection, ".rodata", ".data")
	#printf("=====================================================================================================\n")

	# print out total and section size summary
	if("" == t) {
		printf("%-46s%16s%16s%16s%16s\n", SRCFILENAME, sprintf("0x%x",totalSize), sprintf("0x%x",sectionSize[codeSection]),
										  sprintf("0x%x",sectionSize[".rodata"]), sprintf("0x%x",sectionSize[".data"]))
	}

	#4.3 printout the size of a certain segment
	if (SEGTYPE == ".text") {
		printf("0x%x\n",sectionSize[codeSection])
	}
	else if (".rodata" == SEGTYPE) {
		printf("0x%x\n",sectionSize[".rodata"])
	}
	else if (".data" == SEGTYPE) {
		printf("0x%x\n",sectionSize[".data"])
	}

	#4.4 printout Debugging Accumulation info include .text .rodata .data and total size
	# if debugging option's on, print section accumuation size as well
	if (d){
		sectionAccSize[".total"] = accSize
		for (section in sectionSize) {
			sectionAccSize[".total"] += moduleSize[section]["*fill*"]

			if (sectionSize[section]){
				for (module in moduleSize[section]){
					sectionAccSize[section] += moduleSize[section][module]
				}
			}
		}
		printf("%-36s%16s%16s%16s%16s\n", "Debugging Accumulation", sprintf("0x%x",sectionAccSize[".total"]), sprintf("0x%x",sectionAccSize[codeSection]),
										  sprintf("0x%x",sectionAccSize[".rodata"]), sprintf("0x%x",sectionAccSize[".data"]))
	}

	#4.5 printout primary goals's total .text .rodata and .data size.
	#print out module size summary
	if (MODULECOUNT) {
		printf("=============================================Module_List=============================================\n")
		i = 0
		#for循环依次取二级数组moduleSize[".total"]的二级下标
		for (module in moduleSize[".total"]) {
			#print "module="module
			#print "moduleSize[.total]"
			printf("%-36.36s%16s%16s%16s%16s\n", sprintf("%s",module),
									  sprintf("0x%x",moduleSize[".total"][module]),
									  sprintf("0x%x",moduleSize[codeSection][module]),
									  sprintf("0x%x",moduleSize[".rodata"][module]),
									  sprintf("0x%x",moduleSize[".data"][module]))
			if (++i >= MODULECOUNT)
				break
		}
	}

	#4.6 printout secondary goals's total .text .rodata and .data size.
	if (SUBOBJCOUNT) {
		i = 0
		for (module in moduleSize[".total"]) {
			#print "isContainObj["module"]="isContainObj[module]
			if (isContainObj[module] == 0) {
				continue
			}

			printf("=============================================SubObj_List=============================================\n")

			printf("%-36.36s%16s%16s%16s%16s\n", sprintf("%s",module),
									  sprintf("0x%x",moduleSize[".total"][module]),
									  sprintf("0x%x",moduleSize[codeSection][module]),
									  sprintf("0x%x",moduleSize[".rodata"][module]),
									  sprintf("0x%x",moduleSize[".data"][module]))

			j = 0
			for (subObj in subObjSize[module][".total"]) {
				printf("%-36.36s%16s%16s%16s%16s\n", subObj,
												  sprintf("0x%x",subObjSize[module][".total"][subObj]),
												  sprintf("0x%x",subObjSize[module][codeSection][subObj]),
												  sprintf("0x%x",subObjSize[module][".rodata"][subObj]),
												  sprintf("0x%x",subObjSize[module][".data"][subObj]))
				if (++j >= SUBOBJCOUNT)
					break
			}

			if (++i >= MODULECOUNT)
				break
		}
	}

	#printf("#####################################################################################################\n")	
}

