diff --git a/attributes.pr b/attributes.pr new file mode 100644 index 00000000..3f4e3b94 --- /dev/null +++ b/attributes.pr @@ -0,0 +1,176 @@ +import libdwarf +import map + +import merge + +export type Attr = interface { + // TODO These should both return a status I think + def read(attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) + def write(obj: &merge::Object, die: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, err: **s_Dwarf_Error_s) +} + +type AddressData = struct { + symbol: uint64 + offset: uint64 +} +type ExpressionData = struct { + op: uint8 + val1: uint64 + val2: uint64 +} + +let attributes = map::make(int, type *runtime::Type) +attributes[0x3f] = type AT_external +attributes[0x03] = type AT_name +attributes[0x3a] = type AT_decl_file +attributes[0x3b] = type AT_decl_line +attributes[0x39] = type AT_decl_column +attributes[0x27] = type AT_prototyped +attributes[0x49] = type AT_type +attributes[0x11] = type AT_low_pc +attributes[0x12] = type AT_high_pc +attributes[0x40] = type AT_frame_base +attributes[0x25] = type AT_producer +attributes[0x13] = type AT_language +attributes[0x1b] = type AT_comp_dir + +export def parse(attribute: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) -> &Attr { + var kind: ushort + dwarf_whatattr(attribute, *kind, err) + + if not attributes.contains(kind) { + error("Unknown attribute: ", kind, ", skipping\n") + return null + } + + let tpe = attributes[kind] + let instance = zero_allocate(tpe.size) + let ref = make_ref(tpe, instance) + let attr = ref !&Attr + + attr.read(attribute, err) + //print("Read attribute of type ", tpe.name, "\n") + return attr +} + +// Attributes +type AT_external = struct { data: bool } +export def read(at: &AT_external, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var flag: int + dwarf_formflag(attr, *flag, err) + at.data = flag !bool +} +export def write(at: &AT_external, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_flag_a(obj.pdbg, pdie.die, 0x3f !ushort, at.data !uint8, attr, error) +} + +type AT_name = struct { data: Str } +export def read(at: &AT_name, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var str: *char + dwarf_formstring(attr, *str, err) + at.data = make_string(str) +} +export def write(at: &AT_name, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_name_a(pdie.die, at.data.to_array().value, attr, error) +} + +type AT_producer = struct { data: Str } +export def read(at: &AT_producer, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var str: *char + dwarf_formstring(attr, *str, err) + at.data = make_string(str) +} +export def write(at: &AT_producer, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_producer_a(pdie.die, at.data.to_array().value, attr, error) +} + +type AT_decl_file = struct { data: uint64 } +export def read(at: &AT_decl_file, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formudata(attr, *at.data, err) +} +export def write(at: &AT_decl_file, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x3a !ushort, at.data, attr, error) +} + +type AT_decl_line = struct { data: uint64 } +export def read(at: &AT_decl_line, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formudata(attr, *at.data, err) +} +export def write(at: &AT_decl_line, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x3b !ushort, at.data, attr, error) +} + +type AT_decl_column = struct { data: uint64 } +export def read(at: &AT_decl_column, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formudata(attr, *at.data, err) +} +export def write(at: &AT_decl_column, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x39 !ushort, at.data, attr, error) +} + +type AT_prototyped = struct { data: bool } +export def read(at: &AT_prototyped, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var flag: int + dwarf_formflag(attr, *flag, err) + at.data = flag !bool +} +export def write(at: &AT_prototyped, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_flag_a(obj.pdbg, pdie.die, 0x27 !ushort, at.data !uint8, attr, error) +} + +type AT_type = struct { data: uint64 } +export def read(at: &AT_type, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var is_info: int + dwarf_formref(attr, *at.data, *is_info, err) +} +export def write(at: &AT_type, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_reference_c(obj.pdbg, pdie.die, 0x49 !ushort, null, attr, error) + obj.add_reference_marker(pdie, 0x49 !ushort, at.data) +} + +type AT_low_pc = struct { data: AddressData } +export def read(at: &AT_low_pc, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formaddr(attr, *at.data.offset, err) // TODO find the symbol +} +export def write(at: &AT_low_pc, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_targ_address_c(obj.pdbg, pdie.die, 0x11 !ushort, at.data.offset, at.data.symbol, attr, error) +} + +type AT_high_pc = struct { data: uint64 } +export def read(at: &AT_high_pc, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formudata(attr, *at.data, err) +} +export def write(at: &AT_high_pc, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x12 !ushort, at.data, attr, error) +} + +type AT_frame_base = struct { data: ExpressionData } +export def read(at: &AT_frame_base, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var length: uint64 + var data: * + dwarf_formexprloc(attr, *length, *data, err) +} +export def write(at: &AT_frame_base, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + var expr: *s_Dwarf_P_Expr_s + dwarf_new_expr_a(obj.pdbg, *expr, error) + dwarf_add_expr_gen_a(expr, at.data.op, at.data.val1, at.data.val2, null, error) + dwarf_add_AT_location_expr_a(obj.pdbg, pdie.die, 0x40 !ushort, expr, attr, error) +} + +type AT_language = struct { data: uint64 } +export def read(at: &AT_language, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + dwarf_formudata(attr, *at.data, err) +} +export def write(at: &AT_language, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x13 !ushort, at.data, attr, error) +} + +type AT_comp_dir = struct { data: Str } +export def read(at: &AT_comp_dir, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { + var str: *char + dwarf_formstring(attr, *str, err) + at.data = make_string(str) +} +export def write(at: &AT_comp_dir, obj: &merge::Object, pdie: &merge::DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { + dwarf_add_AT_comp_dir_a(pdie.die, at.data.to_array().value, attr, error) +} \ No newline at end of file diff --git a/main.pr b/main.pr new file mode 100644 index 00000000..f7061ccb --- /dev/null +++ b/main.pr @@ -0,0 +1,59 @@ +import merge + +const file_a = "A.o" +const file_b = "B.o" +const file_r = "AB2.o" + +def main { + let obj_a = open_object_read(file_a) + let obj_b = open_object_read(file_b) + let new_obj = open_object_write(file_r) + new_obj.copy_arch_mach(obj_a) + + obj_a.initialize_section(".text") + obj_a.initialize_section(".data") + obj_a.initialize_section(".llvm_addrsig") + + obj_b.initialize_section(".text") + obj_b.initialize_section(".data") + obj_b.initialize_section(".llvm_addrsig") + + obj_a.load_symbols() + obj_b.load_symbols() + + obj_a.load_section_data(".text") + obj_a.load_section_data(".data") + obj_a.load_section_data(".llvm_addrsig") + + obj_b.load_section_data(".text") + obj_b.load_section_data(".data") + obj_b.load_section_data(".llvm_addrsig") + + new_obj.merge_section_data(obj_a, ".text") + new_obj.merge_section_data(obj_a, ".data") + new_obj.merge_section_data(obj_a, ".llvm_addrsig") + + new_obj.merge_section_data(obj_b, ".text") + new_obj.merge_section_data(obj_b, ".data") + new_obj.merge_section_data(obj_b, ".llvm_addrsig") + + new_obj.copy_symbols(obj_a) + new_obj.copy_symbols(obj_b) + + new_obj.copy_debug_info(obj_a) + new_obj.copy_debug_info(obj_b) + + new_obj.write_debug_info() + new_obj.write_symbols() + new_obj.write_debug_sections() + + new_obj.write_section_data(".text") + new_obj.write_section_data(".data") + new_obj.write_section_data(".llvm_addrsig") + + delete(new_obj) + delete(obj_a) + delete(obj_b) +} + +main \ No newline at end of file diff --git a/bfd_merge.pr b/merge.pr similarity index 72% rename from bfd_merge.pr rename to merge.pr index 5f68e01d..aa02065f 100644 --- a/bfd_merge.pr +++ b/merge.pr @@ -4,9 +4,7 @@ import map import vector import linux -const file_a = "A.o" -const file_b = "B.o" -const file_r = "AB2.o" +import attributes const DW_AT_low_pc: ushort = 0x11 const DW_AT_high_pc: ushort = 0x12 @@ -20,7 +18,7 @@ const DW_DLV_NO_ENTRY = -1 const DW_TAG_compile_unit = 0x11 -type DIE = struct { +export type DIE = struct { obj: weak_ref(Object) // Owner offset: size_t tag: ushort @@ -34,148 +32,6 @@ type DIE = struct { die: *s_Dwarf_P_Die_s } -type Attr = interface { - // TODO These should both return a status I think - def read(attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) - def write(obj: &Object, die: &DIE, attr: **s_Dwarf_P_Attribute_s, err: **s_Dwarf_Error_s) -} - -type AddressData = struct { - symbol: uint64 - offset: uint64 -} -type ExpressionData = struct { - op: uint8 - val1: uint64 - val2: uint64 -} - -let attributes = map::make(int, type *runtime::Type) -attributes[0x3f] = type AT_external -attributes[0x03] = type AT_name -attributes[0x3a] = type AT_decl_file -attributes[0x3b] = type AT_decl_line -attributes[0x39] = type AT_decl_column -attributes[0x27] = type AT_prototyped -attributes[0x49] = type AT_type -attributes[0x11] = type AT_low_pc -attributes[0x12] = type AT_high_pc -attributes[0x40] = type AT_frame_base - -def parse(attribute: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) -> &Attr { - var kind: ushort - dwarf_whatattr(attribute, *kind, err) - - if not attributes.contains(kind) { - error("Unknown attribute: ", kind, ", skipping\n") - return null - } - - let tpe = attributes[kind] - let instance = zero_allocate(tpe.size) - let ref = make_ref(tpe, instance) - let attr = ref !&Attr - - attr.read(attribute, err) - print("Read attribute of type ", tpe.name, "\n") - return attr -} - -// Attributes -type AT_external = struct { data: bool } -def read(at: &AT_external, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - var flag: int - dwarf_formflag(attr, *flag, err) - at.data = flag !bool -} -def write(at: &AT_external, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_flag_a(obj.pdbg, pdie.die, 0x3f !ushort, at.data !uint8, attr, error) -} - -type AT_name = struct { data: string } -def read(at: &AT_name, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - var str: *char - dwarf_formstring(attr, *str, err) - at.data.value = str -} -def write(at: &AT_name, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_name_a(pdie.die, at.data.value, attr, error) -} - -type AT_decl_file = struct { data: uint64 } -def read(at: &AT_decl_file, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - dwarf_formudata(attr, *at.data, err) -} -def write(at: &AT_decl_file, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x3a !ushort, at.data, attr, error) -} - -type AT_decl_line = struct { data: uint64 } -def read(at: &AT_decl_line, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - dwarf_formudata(attr, *at.data, err) -} -def write(at: &AT_decl_line, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x3b !ushort, at.data, attr, error) -} - -type AT_decl_column = struct { data: uint64 } -def read(at: &AT_decl_column, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - dwarf_formudata(attr, *at.data, err) -} -def write(at: &AT_decl_column, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x39 !ushort, at.data, attr, error) -} - -type AT_prototyped = struct { data: bool } -def read(at: &AT_prototyped, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - var flag: int - dwarf_formflag(attr, *flag, err) - at.data = flag !bool -} -def write(at: &AT_prototyped, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_flag_a(obj.pdbg, pdie.die, 0x27 !ushort, at.data !uint8, attr, error) -} - -type AT_type = struct { data: uint64 } -def read(at: &AT_type, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - var is_info: int - dwarf_formref(attr, *at.data, *is_info, err) -} -def write(at: &AT_type, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_reference_c(obj.pdbg, pdie.die, 0x49 !ushort, null, attr, error) - obj.add_reference_marker(pdie, 0x49 !ushort, at.data) -} - -type AT_low_pc = struct { data: AddressData } -def read(at: &AT_low_pc, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - dwarf_formaddr(attr, *at.data.offset, err) // TODO find the symbol -} -def write(at: &AT_low_pc, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_targ_address_c(obj.pdbg, pdie.die, 0x11 !ushort, at.data.offset, at.data.symbol, attr, error) -} - -type AT_high_pc = struct { data: uint64 } -def read(at: &AT_high_pc, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - dwarf_formudata(attr, *at.data, err) -} -def write(at: &AT_high_pc, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - dwarf_add_AT_unsigned_const_a(obj.pdbg, pdie.die, 0x12 !ushort, at.data, attr, error) -} - -type AT_frame_base = struct { data: ExpressionData } -def read(at: &AT_frame_base, attr: *s_Dwarf_Attribute_s, err: **s_Dwarf_Error_s) { - var length: uint64 - var data: * - dwarf_formexprloc(attr, *length, *data, err) -} -def write(at: &AT_frame_base, obj: &Object, pdie: &DIE, attr: **s_Dwarf_P_Attribute_s, error: **s_Dwarf_Error_s) { - var expr: *s_Dwarf_P_Expr_s - dwarf_new_expr_a(obj.pdbg, *expr, error) - dwarf_add_expr_gen_a(expr, at.data.op, at.data.val1, at.data.val2, null, error) - dwarf_add_AT_location_expr_a(obj.pdbg, pdie.die, 0x40 !ushort, expr, attr, error) -} - - type Section = struct { offsets: &Map(&Section, size_t) section: *s_bfd_section @@ -206,7 +62,7 @@ export def hash(sec: &Section) -> uint64 { return sec !*uint64 !uint64 } -type Object = struct { +export type Object = struct { bfd: *s_bfd sections: &SMap(&Section) symtab: **s_bfd_symbol @@ -224,14 +80,14 @@ type Object = struct { reference_markers: &Vector(ReferenceMarker) } -type ReferenceMarker = struct { +export type ReferenceMarker = struct { die: &DIE attr: ushort addr: uint64 } -def add_reference_marker(o: &Object, die: &DIE, attr: ushort, addr: uint64) { - print("Inserting marker for die ", die.die !*, "\n") +export def add_reference_marker(o: &Object, die: &DIE, attr: ushort, addr: uint64) { + //print("Inserting marker for die ", die.die !*, "\n") o.reference_markers.push({die, attr, addr} !ReferenceMarker) } @@ -255,7 +111,7 @@ def find_symbol(o: &Object, origin: &Object, section: &Section, reloc: *s_reloc_ return null } -def delete_symbol(o: &Object, name: Str) { +export def delete_symbol(o: &Object, name: Str) { for var i in 0..o.symbols.length { let sym = o.symbols[i] if sym.name == name { @@ -265,7 +121,7 @@ def delete_symbol(o: &Object, name: Str) { } } -def open_object_read(file: Str) -> &Object { +export def open_object_read(file: Str) -> &Object { let path = file.to_array() let abfd = bfd_openr(path.value, null) bfd_check_format(abfd, e_bfd_format::bfd_object) @@ -303,33 +159,36 @@ def bfd_write_callback( } } - if tpe != 9 and not has_created_section { // 9 is for the rel section but don't ask me why - - let section = bfd_make_section(obj.bfd, name) + if tpe != 9 { // 9 is for the rel section but don't ask me why + @sect_name_index = obj.sym_size + if not has_created_section { + let section = bfd_make_section(obj.bfd, name) - obj.symtab = reallocate(obj.symtab, (obj.sym_size + 1) * size_of *s_bfd_symbol) - let symbol = obj.bfd.xvec._bfd_make_empty_symbol(obj.bfd) - symbol.section = section - symbol.flags = 0x1 /* BSF_LOCAL */ | 0x100 /* BSF_SECTION_SYM */ + obj.symtab = reallocate(obj.symtab, (obj.sym_size + 1) * size_of *s_bfd_symbol) + let symbol = obj.bfd.xvec._bfd_make_empty_symbol(obj.bfd) + symbol.section = section + symbol.flags = 0x1 /* BSF_LOCAL */ | 0x100 /* BSF_SECTION_SYM */ - obj.symtab[obj.sym_size] = symbol - @sect_name_index = obj.sym_size + obj.symtab[obj.sym_size] = symbol - obj.symbols.push({ null, make_string(name), symbol, null, 0, 0, 0, obj.sym_size } !&Symbol) - obj.sym_size += 1 + obj.symbols.push({ null, make_string(name), symbol, null, 0, 0, 0, obj.sym_size } !&Symbol) + + obj.debug_sections.push({ + section = section, + name = namep, + index = obj.section_index + } !&DebugSection) + } - obj.debug_sections.push({ - section = section, - name = namep, - index = obj.section_index - } !&DebugSection) + obj.sym_size += 1 } + obj.section_index += 1 return obj.section_index - 1 } -def open_object_write(file: Str) -> &Object { +export def open_object_write(file: Str) -> &Object { let path = file.to_array() let abfd = bfd_openw(path.value, null) bfd_set_format(abfd, e_bfd_format::bfd_object) @@ -346,11 +205,11 @@ def open_object_write(file: Str) -> &Object { return obj } -def copy_arch_mach(to: &Object, frm: &Object) { +export def copy_arch_mach(to: &Object, frm: &Object) { to.bfd.xvec._bfd_set_arch_mach(to.bfd, bfd_get_arch(frm.bfd), bfd_get_mach(frm.bfd)) } -def delete(obj: &Object) { +export def delete(obj: &Object) { bfd_close(obj.bfd) if obj.dbg { @@ -365,7 +224,7 @@ def delete(obj: &Object) { } } -def copy_debug_info(res: &Object, frm: &Object) { +export def copy_debug_info(res: &Object, frm: &Object) { var error: *s_Dwarf_Error_s // TODO actually merge something here res.dies.add_all(frm.dies) @@ -377,7 +236,7 @@ def write_debug_info(o: &Object, die: &DIE, parent: *s_Dwarf_P_Die_s = null, lef var error: *s_Dwarf_Error_s var res: *s_Dwarf_P_Die_s - print("Creating die ", die.tag, "\n") + //print("Creating die ", die.tag, "\n") if dwarf_new_die_a(o.pdbg, die.tag, parent, null, left, null, *res, *error) == DW_DLV_ERROR { dwarf_error(error) } @@ -386,7 +245,7 @@ def write_debug_info(o: &Object, die: &DIE, parent: *s_Dwarf_P_Die_s = null, lef // Attributes for var attr in die.attributes { var dwattr: *s_Dwarf_Attribute_s - print("Writing attribute ", ref_type(attr).tpe.name, "\n") + //print("Writing attribute ", ref_type(attr).tpe.name, "\n") attr.write(o, die, *dwattr, *error) } @@ -408,11 +267,13 @@ def write_debug_info(o: &Object, die: &DIE, parent: *s_Dwarf_P_Die_s = null, lef return res } -def write_debug_info(res: &Object) { +export def write_debug_info(res: &Object) { // Test debug info var error: *s_Dwarf_Error_s var abbrev_offset = 0 + var sym_size = res.sym_size for var die in res.dies { + res.sym_size = sym_size res.section_index = 0 if dwarf_producer_init( @@ -421,6 +282,8 @@ def write_debug_info(res: &Object) { dwarf_error(error) } + if dwarf_pro_set_default_string_form(res.pdbg, /* DW_FORM_strp */0x0e, *error) { dwarf_error(error) } + let ndwdie = write_debug_info(res, die) if dwarf_add_die_to_debug_a(res.pdbg, ndwdie, *error) == DW_DLV_ERROR { dwarf_error(error) @@ -447,6 +310,7 @@ def write_debug_info(res: &Object) { dwarf_error(error) } + var info_section_offset: size_t = 0 for var i in 0..nbufs { let section = res.debug_sections[i] var section_index: uint64 @@ -461,14 +325,19 @@ def write_debug_info(res: &Object) { if section.name == ".debug_info" { var abbr_offset = ((data !*uint8) ++ 6) !*uint32 @abbr_offset = abbrev_offset + + info_section_offset = section.size } else if section.name == ".debug_abbrev" { abbrev_offset += new_section_size + } else if section.name == ".debug_str" { + section.size = 0 // Apparently we write the same data multiple times, there seems to be some data still in the buffer } section.data = reallocate(section.data !*uint8, section.size + new_section_size) !* memcopy(data, section.data ++ section.size, new_section_size) section.size += new_section_size + print("Section ", section.name, " new size ", section.size, "\n") bfd_set_section_size(section.section, section.size) bfd_set_section_flags(section.section, section.section.flags | 0x8 /*SEC_READONLY*/ | 0x100 /*SEC_CONTENTS*/ ) @@ -480,6 +349,7 @@ def write_debug_info(res: &Object) { dwarf_error(error) } + print("Info section size ", info_section_offset, "\n") for var i in 0..nrelocs { var elf_section_index: uint64 var elf_section_index_link: uint64 @@ -504,8 +374,9 @@ def write_debug_info(res: &Object) { let relent = zero_allocate(s_reloc_cache_entry) relent.sym_ptr_ptr = *res.symbols[reld[j].drd_symbol_index].symbol - relent.addend = 0 - relent.address = reld[j].drd_offset + relent.address = reld[j].drd_offset + info_section_offset + relent.addend = @((sec.data !*uint8 ++ relent.address) !*uint32) + print(relent.addend, "\n") relent.howto = bfd_reloc_type_lookup(res.bfd, e_bfd_reloc_code_real::BFD_RELOC_32 if reld.drd_length == 4 else e_bfd_reloc_code_real::BFD_RELOC_64) sec.relocations.reloc[sec.relocations.count + j] = relent } @@ -515,15 +386,15 @@ def write_debug_info(res: &Object) { res.bfd.xvec._bfd_set_reloc(res.bfd, sec.section, sec.relocations.reloc, sec.relocations.count !uint) } - //dwarf_reset_section_bytes(res.pdbg) - if dwarf_producer_finish_a(res.pdbg, *error) == DW_DLV_ERROR { dwarf_error(error) } + + dwarf_reset_section_bytes(res.pdbg) } } -def write_debug_sections(res: &Object) { +export def write_debug_sections(res: &Object) { for var i in 0..res.debug_sections.length { let section = res.debug_sections[i] @@ -547,13 +418,13 @@ def bfd_asymbol_value(sy: *s_bfd_symbol) -> size_t { return sy.section.vma + sy.value } -def initialize_section(res: &Object, name: Str) { +export def initialize_section(res: &Object, name: Str) { let sec = bfd_get_section_by_name(res.bfd, name.to_array().value) if not sec { return } res.sections[name] = { section = sec, name = name.to_array(), offsets = map::make(type &Section, size_t), size = sec.size} !&Section } -def load_section_data(obj: &Object, name: Str) { +export def load_section_data(obj: &Object, name: Str) { if not obj.sections.contains(name) { return } let section = obj.sections[name] var data = allocate(section.section.size) @@ -561,7 +432,7 @@ def load_section_data(obj: &Object, name: Str) { section.data = data } -def merge_section(res: &Object, obj_a: &Object, name: Str) { +export def merge_section(res: &Object, obj_a: &Object, name: Str) { if not obj_a.sections.contains(name) { return } let a_sec = obj_a.sections[name] @@ -580,7 +451,7 @@ def merge_section(res: &Object, obj_a: &Object, name: Str) { res.sections[name] = section } -def merge_section_data(res: &Object, obj_a: &Object, name: Str) { +export def merge_section_data(res: &Object, obj_a: &Object, name: Str) { if not obj_a.sections.contains(name) { return } merge_section(res, obj_a, name) @@ -631,7 +502,7 @@ def merge_section_data(res: &Object, obj_a: &Object, name: Str) { bfd_set_section_size(new_sec.section, new_sec.size) } -def write_section_data(res: &Object, name: Str) { +export def write_section_data(res: &Object, name: Str) { if not res.sections.contains(name) { return } let sec = res.sections[name] bfd_set_section_contents(res.bfd, sec.section, sec.data, 0, sec.size) @@ -654,7 +525,7 @@ def write_section_data(res: &Object, name: Str) { } } -def load_symbols(res: &Object) { +export def load_symbols(res: &Object) { let a_sz = res.bfd.xvec._bfd_get_symtab_upper_bound(res.bfd) let syms = allocate(a_sz) !**s_bfd_symbol let cnta = res.bfd.xvec._bfd_canonicalize_symtab(res.bfd, syms) @@ -697,7 +568,7 @@ def load_symbols(res: &Object) { } // returns the difference in size when a symbol is deleted -def remove_symbol(res: &Object, name: Str) -> int { +export def remove_symbol(res: &Object, name: Str) -> int { if find_symbol(res, name) == null { return 0 } let sym = find_symbol(res, name) let sec = sym.section @@ -764,7 +635,7 @@ type DuplicateEntry = struct { from_section: &Section } -def copy_symbols(to: &Object, frm: &Object) { +export def copy_symbols(to: &Object, frm: &Object) { to.symtab = reallocate(to.symtab, size_of *s_bfd_symbol * (frm.sym_size + to.sym_size)) !**s_bfd_symbol let duplicates = map::make(DuplicateEntry) @@ -926,7 +797,7 @@ def read_dwarf_die(obj: &Object, in_die: *s_Dwarf_Die_s, is_info: int, in_level: return first_die } -def read_dwarf_symbols(o: &Object) { +export def read_dwarf_symbols(o: &Object) { var error: *s_Dwarf_Error_s @@ -972,60 +843,6 @@ def read_dwarf_symbols(o: &Object) { } } -def write_symbols(res: &Object) { +export def write_symbols(res: &Object) { bfd_set_symtab(res.bfd, res.symtab, res.sym_size !uint) } - -def main { - let obj_a = open_object_read(file_a) - let obj_b = open_object_read(file_b) - let new_obj = open_object_write(file_r) - new_obj.copy_arch_mach(obj_a) - - obj_a.initialize_section(".text") - obj_a.initialize_section(".data") - obj_a.initialize_section(".llvm_addrsig") - - obj_b.initialize_section(".text") - obj_b.initialize_section(".data") - obj_b.initialize_section(".llvm_addrsig") - - obj_a.load_symbols() - obj_b.load_symbols() - - obj_a.load_section_data(".text") - obj_a.load_section_data(".data") - obj_a.load_section_data(".llvm_addrsig") - - obj_b.load_section_data(".text") - obj_b.load_section_data(".data") - obj_b.load_section_data(".llvm_addrsig") - - new_obj.merge_section_data(obj_a, ".text") - new_obj.merge_section_data(obj_a, ".data") - new_obj.merge_section_data(obj_a, ".llvm_addrsig") - - new_obj.merge_section_data(obj_b, ".text") - new_obj.merge_section_data(obj_b, ".data") - new_obj.merge_section_data(obj_b, ".llvm_addrsig") - - new_obj.copy_symbols(obj_a) - new_obj.copy_symbols(obj_b) - - new_obj.copy_debug_info(obj_a) - new_obj.copy_debug_info(obj_b) - - new_obj.write_debug_info() - new_obj.write_symbols() - new_obj.write_debug_sections() - - new_obj.write_section_data(".text") - new_obj.write_section_data(".data") - new_obj.write_section_data(".llvm_addrsig") - - delete(new_obj) - delete(obj_a) - delete(obj_b) -} - -main