func ParseMapFileSizes()

in newt/builder/size.go [168:350]


func ParseMapFileSizes(fileName string) (map[string]*PkgSize, error) {
	var state int = 0

	file, err := os.Open(fileName)
	if err != nil {
		return nil, util.NewNewtError("Mapfile failed: " + err.Error())
	}

	var symName string = ""

	globalMemSections = make(map[string]*MemSection)
	pkgSizes := make(map[string]*PkgSize)
	scanner := bufio.NewScanner(file)
	for scanner.Scan() {
		switch state {
		case 0:
			if strings.Contains(scanner.Text(), "Memory Configuration") {
				state = 1
			}
		case 1:
			if strings.Contains(scanner.Text(), "Origin") {
				state = 2
			}
		case 2:
			if strings.Contains(scanner.Text(), "*default*") {
				state = 3
				continue
			}
			array := strings.Fields(scanner.Text())
			offset, err := strconv.ParseUint(array[1], 0, 64)
			if err != nil {
				return nil, util.NewNewtError("Can't parse mem info")
			}
			size, err := strconv.ParseUint(array[2], 0, 64)
			if err != nil {
				return nil, util.NewNewtError("Can't parse mem info")
			}
			globalMemSections[array[0]] = MakeMemSection(array[0], offset,
				size)
		case 3:
			if strings.Contains(scanner.Text(),
				"Linker script and memory map") {
				state = 4
			}
		case 4:
			var addrStr string = ""
			var sizeStr string = ""
			var srcFile string = ""

			if strings.Contains(scanner.Text(), "/DISCARD/") ||
				strings.HasPrefix(scanner.Text(), "OUTPUT(") {
				/*
				 * After this there is only discarded symbols
				 */
				state = 5
				continue
			}

			array := strings.Fields(scanner.Text())

			switch len(array) {
			case 1:
				/*
				 * section name on it's own, e.g.
				 * *(.text*)
				 *
				 * section name + symbol name, e.g.
				 * .text.Reset_Handler
				 *
				 * ignore these for now
				 */
				symName = array[0]
				continue
			case 2:
				/*
				 * Either stuff from beginning to first useful data e.g.
				 * END GROUP
				 *
				 * or address of symbol + symbol name, e.g.
				 * 0x00000000080002c8                SystemInit
				 *
				 * or section names with multiple input things, e.g.
				 * *(.ARM.extab* .gnu.linkonce.armextab.*)
				 *
				 * or space set aside in linker script e.g.
				 * 0x0000000020002e80      0x400
				 * (that's the initial stack)
				 *
				 * ignore these for now
				 */
				continue
			case 3:
				/*
				 * address, size, and name of file, e.g.
				 * 0x000000000800bb04     0x1050 /Users/marko/foo/tadpole/hw//mcu/stm/stm32f3xx/bin/blinky_f3/libstm32f3xx.a(stm32f30x_syscfg.o)
				 *
				 * padding, or empty areas defined in linker script:
				 * *fill*         0x000000000800cb71        0x3
				 *
				 * output section name, location, size, e.g.:
				 * .bss            0x0000000020000ab0     0x23d0
				 */
				/*
				 * Record addr, size and name to find library.
				 */
				if array[0] == "*fill*" {
					addrStr = array[1]
					sizeStr = array[2]
					srcFile = array[0]
					symName = array[0]
				} else {
					addrStr = array[0]
					sizeStr = array[1]
					srcFile = array[2]
				}
			case 4:
				/*
				 * section, address, size, name of file, e.g.
				 * COMMON         0x0000000020002d28        0x8 /Users/marko/foo/tadpole/libs//os/bin/blinky_f3/libos.a(os_arch_arm.o)
				 *
				 * linker script symbol definitions:
				 * 0x0000000020002e80                _ebss = .
				 *
				 * crud, e.g.:
				 * 0x8 (size before relaxing)
				 */
				symName = array[0]
				addrStr = array[1]
				sizeStr = array[2]
				srcFile = array[3]
			default:
				continue
			}
			addr, err := strconv.ParseUint(addrStr, 0, 64)
			if err != nil {
				continue
			}
			size, err := strconv.ParseUint(sizeStr, 0, 64)
			if err != nil {
				continue
			}
			if size == 0 {
				continue
			}

			// srcFile might be : mylib.a(object_file.o) or object_file.o
			tmpStrArr := strings.Split(srcFile, "(")
			srcLib := tmpStrArr[0]
			objName := ""
			if srcLib != "*fill*" {
				if len(tmpStrArr) > 1 {
					tmpStrArr = strings.Split(tmpStrArr[1], ")")
					objName = tmpStrArr[0]
				} else {
					objName = filepath.Base(tmpStrArr[0])
				}
			}
			tmpStrArr = strings.Split(symName, ".")
			if len(tmpStrArr) > 2 {
				if tmpStrArr[1] == "rodata" && tmpStrArr[2] == "str1" {
					symName = ".rodata.str1"
				} else {
					symName = tmpStrArr[2]
				}
			}
			pkgSize := pkgSizes[srcLib]
			if pkgSize == nil {
				pkgSize = MakePkgSize(srcLib)
				pkgSizes[srcLib] = pkgSize
			}
			pkgSize.addSymSize(symName, objName, uint32(size), addr)
			symName = ".unknown"
		default:
		}
	}
	file.Close()
	for name, section := range globalMemSections {
		util.StatusMessage(util.VERBOSITY_VERBOSE, "Mem %s: 0x%x-0x%x\n",
			name, section.Offset, section.EndOff)
	}

	return pkgSizes, nil
}