| #!/usr/bin/env python3 |
| import sys |
| import argparse |
| import os |
| import re |
| import string |
| from elftools.elf.elffile import ELFFile |
| |
| partitions=[] |
| variables=[] |
| |
| app_smem = "/*\n * The following is a dynamically created linker section.\n" \ |
| " * Please do not modify or delete.\n */\n" |
| dRegion_size = { "0x20":32 , \ |
| "0x40":64, \ |
| "0x80":128, \ |
| "0x100":256, \ |
| "0x200":512, \ |
| "0x400":1024, \ |
| "0x800":2048, \ |
| "0x1000":4096, \ |
| "0x2000":8192, \ |
| "0x4000":16384, \ |
| "0x8000":32768, \ |
| "0x10000":65536, \ |
| "0x20000":131072, \ |
| "0x40000":262144, \ |
| "0x80000":524288, \ |
| "0x100000":1048576, \ |
| "0x200000":2097152, \ |
| "0x400000":4194304, \ |
| "0x800000":8388608, \ |
| "0x1000000":16777216, \ |
| "0x2000000":33554432, \ |
| "0x4000000":67108864, \ |
| "0x8000000":134217728, \ |
| "0x10000000":268435456, \ |
| "0x20000000":536870912, \ |
| "0x40000000":1073741824, \ |
| "0x80000000":2147483648, \ |
| "0x100000000":4294967296} |
| |
| def build_linker_section(filename, regionSizes): |
| with open(filename, 'w') as f: |
| f.write(app_smem) |
| for part in partitions: |
| psize = "0" |
| if (part.endswith("b")): |
| continue |
| for partition, size in regionSizes: |
| if (partition == str(part).strip("b'")): |
| f.write("\t\t. = ALIGN(" + size + ");\n"); |
| psize = size |
| f.write("\t\t" + str(part).strip("b'") + " = .;\n") |
| f.write("\t\t*(SORT(" + str(part).strip("b'") + "*))\n") |
| f.write("\t\t. = ALIGN(_app_data_align);\n") |
| f.write("\t\t" + str(part).strip("b'") + "b_end = .;\n") |
| f.write("\t\t. = ALIGN(" + psize + ");\n") |
| |
| |
| def find_variables(filename): |
| flag = 0 |
| with open(filename, 'rb') as f: |
| objF = ELFFile( f) |
| if (not objF): |
| print("Error parsing file: ",filename) |
| os.exit(1) |
| sec = [ x for x in objF.iter_sections()] |
| for s in sec: |
| if ("smem" in s.name and not ".rel" in s.name): |
| variables.append( s) |
| |
| |
| def build_partitions(): |
| global partitions |
| s = set() |
| for var in variables: |
| s.add(var.name) |
| for sec in sorted(s): |
| partitions.append(sec) |
| |
| def calc_sec_size(): |
| d = dict() |
| if not variables: |
| return None |
| for v in variables: |
| if( v.name in d): |
| d[v.name] += v.header.sh_size |
| else: |
| d[v.name] = v.header.sh_size |
| return d |
| |
| def genRegionDef(): |
| res = [] |
| dSecs = calc_sec_size() |
| if(dSecs is None): |
| print("\n***\nError: Failed to identify smem regions in the object files\n***\n") |
| sys.exit(1) |
| ordered_defs = [] |
| for key, value in sorted(dRegion_size.items(), key=lambda o: (o[1],o[0]) ): |
| ordered_defs.append( ( value, key)) |
| |
| ltSecs = sorted(dSecs.items()) |
| szltSecs = len(ltSecs) |
| if( szltSecs % 2 == 1): |
| szltSecs += 1 |
| for r in range(int(szltSecs /2 )): |
| i = r*2 |
| sz = ltSecs[i][1] + ltSecs[1+i][1] |
| for d in ordered_defs: |
| if( sz < d[0]): |
| res.append( ( ltSecs[i][0], d[1])) |
| break |
| return res |
| |
| |
| def parse_args(): |
| global args |
| parser = argparse.ArgumentParser( |
| description=__doc__, |
| formatter_class=argparse.RawDescriptionHelpFormatter) |
| parser.add_argument("-d", "--directory", required=True, |
| help="Root build directory") |
| parser.add_argument("-o", "--output", required=True, |
| help="Output ld file") |
| args = parser.parse_args() |
| |
| |
| def main(): |
| parse_args() |
| startIndex = args.directory |
| fileOutput = args.output |
| for dirpath, dirs, files in os.walk(startIndex): |
| for filename in files: |
| if (filename.endswith(".obj") or filename.endswith(".OBJ")): |
| fullname = os.path.join(dirpath, filename) |
| find_variables(fullname) |
| build_partitions() |
| build_linker_section(fileOutput, genRegionDef()) |
| |
| if __name__ == '__main__': |
| main() |