diff --git a/src/elfmerge/elf_link_elf.c b/src/elfmerge/elf_link_elf.c index 75fb45c287739a57e45c9ba04d764bc976a31638..0beae72224b30a39ec46ca116fcfee701b7c3091 100644 --- a/src/elfmerge/elf_link_elf.c +++ b/src/elfmerge/elf_link_elf.c @@ -1002,7 +1002,7 @@ static int sym_cmp_func(const void *src_sym_a_, const void *src_sym_b_) } static inline Elf64_Addr get_symbol_new_value(elf_link_t *elf_link, elf_file_t *ef, - Elf64_Sym *sym, char *name) + Elf64_Sym *sym, char *name) { if (elf_is_symbol_type_section(sym)) { // section may be delete in out ef, so section symbol can not get new value @@ -1042,7 +1042,7 @@ static inline Elf64_Addr get_symbol_new_value(elf_link_t *elf_link, elf_file_t * } static inline Elf32_Section get_symbol_new_section(elf_link_t *elf_link, elf_file_t *ef, - Elf64_Sym *sym) + Elf64_Sym *sym) { Elf64_Section shndx = sym->st_shndx; @@ -1053,7 +1053,7 @@ static inline Elf32_Section get_symbol_new_section(elf_link_t *elf_link, elf_fil } static inline Elf64_Word get_symbol_new_name(elf_link_t *elf_link, elf_file_t *ef, - Elf64_Sym *sym, Elf64_Word sh_link) + Elf64_Sym *sym, Elf64_Word sh_link) { Elf64_Word name = sym->st_name; Elf64_Shdr *strtab = &ef->sechdrs[sh_link]; @@ -1432,10 +1432,24 @@ int dwarf_get_first_die_of_next_cu(Dwarf_Debug dbg, Dwarf_Die* first_die) return ret; } +// location view pair info in .debug_loc +#define MAX_LVP_NUM 20000 +struct lvp_info { + uint64_t num; //=0 + uint64_t start[MAX_LVP_NUM]; + uint64_t end[MAX_LVP_NUM]; +}; + struct dwarf_bias_info { uint64_t text; uint64_t debug_str; uint64_t debug_line_str; + uint64_t debug_line; + uint64_t debug_loclists; + uint64_t debug_rnglists; + uint64_t debug_info; + + struct lvp_info lvp; }; int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info *bias_info) @@ -1461,7 +1475,6 @@ int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info * Dwarf_Unsigned sov = 0; int ret; - /* todo test if this is needed */ if (attr_form == DW_FORM_implicit_const) { continue; } @@ -1489,9 +1502,26 @@ int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info * break; case DW_FORM_strp: *dst_ptr += bias_info->debug_str; - // printf("offset: %lx, *abbrev_ptr: %x *dst_ptr: %x\n", - // (abbrev_ptr - di_base), - // *(uint32_t *)abbrev_ptr, *dst_ptr); + break; + case DW_FORM_sec_offset: + switch (die->di_abbrev_list->abl_attr[i]){ + case DW_AT_stmt_list: + *dst_ptr += bias_info->debug_line; + break; + case DW_AT_location: + bias_info->lvp.end[bias_info->lvp.num] = *dst_ptr; + *dst_ptr += bias_info->debug_loclists; + break; + case DW_AT_GNU_locviews: + bias_info->lvp.start[bias_info->lvp.num] = *dst_ptr; + *dst_ptr += bias_info->debug_loclists; + bias_info->lvp.num++; + break; + // todo .debug_rnglist + case DW_AT_ranges: + *dst_ptr += bias_info->debug_rnglists; + break; + } break; case DW_FORM_data1: case DW_FORM_data2: @@ -1499,16 +1529,24 @@ int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info * case DW_FORM_data8: /* no need to modify */ break; + // A 2-byte length followed by 0 to 65,535 contiguous information bytes case DW_FORM_block2: + // Immediately in the debugging information entry itself case DW_FORM_string: + case DW_FORM_sdata: + // todo DW_FORM_ref_addr??? case DW_FORM_ref4: case DW_FORM_implicit_const: - case DW_FORM_exprloc: + // DW_AT_location...??? case DW_FORM_flag_present: - case DW_FORM_sec_offset: - /* TODO */ break; + case DW_FORM_exprloc: + case DW_AT_location: + // 0a03 0903 need reloc, 02 01 03 dont? + + break; + case DW_FORM_block4: case DW_FORM_block: case DW_FORM_block1: @@ -1553,7 +1591,7 @@ int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info * } int dwarf_traverse_die(Dwarf_Debug dbg, Dwarf_Die parent_die, - void *di_ptr, struct dwarf_bias_info *bias_info) + void *di_ptr, struct dwarf_bias_info *bias_info) { Dwarf_Die son_die; int res; @@ -1598,58 +1636,576 @@ char *temp_get_file_name(char *name) return result; } -void prep_bias_info(elf_link_t *elf_link, elf_file_t *ef, struct dwarf_bias_info *bias_info) +#define INIT ".init" +#define DEBUG_STR ".debug_str" +#define DEBUG_LINE_STR ".debug_line_str" +#define DEBUG_LINE ".debug_line" +#define DEBUG_LOCLISTS ".debug_loclists" +#define DEBUG_RNGLISTS ".debug_rnglists" +#define DEBUG_INFO ".debug_info" + +uint64_t get_ef_sec_bias(elf_link_t *elf_link, elf_file_t *ef, char *sec_name) +{ + unsigned long d_base_offset = + elf_find_section_by_name(get_out_ef(elf_link), sec_name)->sh_offset; + Elf64_Shdr *d_sec = elf_find_section_by_name(ef, sec_name); + unsigned long d_offset = get_new_offset_by_old_offset( + elf_link, ef, d_sec->sh_offset + ); + return d_offset - d_base_offset; +} + +struct dwarf_bias_info* init_prep_bias_info(elf_link_t *elf_link) { - /* .text starts from .init */ - unsigned long text_base_addr = - elf_find_section_by_name(ef, ".init")->sh_addr; - unsigned long ds_base_offset = - elf_find_section_by_name(get_out_ef(elf_link), ".debug_str")->sh_offset; - unsigned long dls_base_offset = - elf_find_section_by_name(get_out_ef(elf_link), ".debug_line_str")->sh_offset; + struct dwarf_bias_info* dbi = + (struct dwarf_bias_info*)malloc(elf_link->in_ef_nr * sizeof(struct dwarf_bias_info)); + for (unsigned int i=0; i < elf_link->in_ef_nr; i++) { + unsigned long text_base_addr = elf_find_section_by_name(&elf_link->in_efs[i], INIT)->sh_addr; + Elf64_Shdr *text_sec = elf_find_section_by_name(&elf_link->in_efs[i], INIT); + unsigned long text_addr = get_new_addr_by_old_addr(elf_link, &elf_link->in_efs[i], text_sec->sh_addr); + dbi[i].text = text_addr - text_base_addr; - Elf64_Shdr *text_sec = elf_find_section_by_name(ef, ".init"); - unsigned long text_addr = get_new_addr_by_old_addr( - elf_link, ef, text_sec->sh_addr - ); - Elf64_Shdr *ds_sec = elf_find_section_by_name(ef, ".debug_str"); - unsigned long ds_offset = get_new_offset_by_old_offset( - elf_link, ef, ds_sec->sh_offset - ); - Elf64_Shdr *dls_sec = elf_find_section_by_name(ef, ".debug_line_str"); - unsigned long dls_offset = get_new_offset_by_old_offset( - elf_link, ef, dls_sec->sh_offset - ); + dbi[i].debug_str = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_STR); + dbi[i].debug_line_str = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_LINE_STR); + dbi[i].debug_line = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_LINE); + dbi[i].debug_loclists = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_LOCLISTS); + dbi[i].debug_rnglists = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_RNGLISTS); + dbi[i].debug_info = get_ef_sec_bias(elf_link, &elf_link->in_efs[i], DEBUG_INFO); + dbi[i].lvp.num = 0; + } + return dbi; +} + +void skip_leb128(uint8_t** data){ + while (**data & 0x80) { + ++*data; + } + ++*data; +} + +uint64_t read_skip_leb128(uint8_t** data) { + uint64_t result = 0; + uint64_t shift = 0; + uint8_t byte; - bias_info->text = text_addr - text_base_addr; - bias_info->debug_str = ds_offset - ds_base_offset; - bias_info->debug_line_str = dls_offset - dls_base_offset; - SI_LOG_DEBUG("%s, text: %lx, debug_str: %lx, debug_line_str: %lx\n", - ef->file_name, - bias_info->text, bias_info->debug_str, bias_info->debug_line_str); - SI_LOG_DEBUG("text_addr: %lx, out_text_base_addr: %lx\n", - text_addr, text_base_addr); + do { + byte = **data; + ++*data; + result |= (byte & 0x7f) << shift; + shift += 7; + } while (byte & 0x80); + + return result; +} + +void old_addr_to_new_skip(uint8_t** data, elf_link_t *elf_link, elf_file_t *ef) { + uint64_t *_addr = (uint64_t*)*data; + *_addr = get_new_offset_by_old_offset(elf_link, ef, *_addr); + *data += 8; } -int modify_debug_info(elf_link_t *elf_link) +void process_extended_line_op(uint8_t ** data, + struct dwarf_bias_info *bias_info) +{ + // LEB128 is mentioned in the document, + // but use byte actually, because max op_code is 0x80 + unsigned long len = read_skip_leb128(data); + uint8_t op_code = **data; + ++*data; + uint64_t *dst_ptr = (uint64_t*)*data; + switch (op_code) { + case DW_LNE_set_address: + *dst_ptr += bias_info->text; + break; + case DW_LNE_end_sequence: + case DW_LNE_define_file: + case DW_LNE_set_discriminator: + case DW_LNE_HP_negate_is_UV_update: + case DW_LNE_HP_push_context: + case DW_LNE_HP_pop_context: + case DW_LNE_HP_set_file_line_column: + case DW_LNE_HP_set_routine_name: + case DW_LNE_HP_set_sequence: + case DW_LNE_HP_negate_post_semantics: + case DW_LNE_HP_negate_function_exit: + case DW_LNE_HP_negate_front_end_logical: + case DW_LNE_HP_define_proc: + break; + default: + si_panic("unknown extended_line_op 0x%x\n", op_code); + break; + } + *data += len - 1; +} + +void modify_line_number_statement( + uint8_t **data, uint8_t *end, + struct dwarf_bias_info *bias_info) +{ + while (*data < end) { + uint8_t op_code = *(uint8_t*)*data; + ++*data; + switch (op_code) + { + // DW_LNS_extended_op + case 0: + process_extended_line_op(data, bias_info); + break; + case DW_LNS_advance_pc: + case DW_LNS_advance_line: + case DW_LNS_set_file: + case DW_LNS_set_column: + case DW_LNS_set_isa: + skip_leb128((uint8_t**)data); + break; + case DW_LNS_copy: + case DW_LNS_negate_stmt: + case DW_LNS_set_basic_block: + case DW_LNS_const_add_pc: + case DW_LNS_fixed_advance_pc: + case DW_LNS_set_prologue_end: + case DW_LNS_set_epilogue_begin: + break; + default: + // si_panic("unknown line_op 0x%x\n", op_code); + break; + } + } +} + +void modify_cu_debug_line(uint8_t **data, struct dwarf_bias_info *bias_info) +{ + // in the.debug_line, the length of CU is recorded at the 4-byte starting with CU, plus 0x4 + uint8_t *end = *data + *(uint32_t *)*data + 0x4; + // skip_header; + *data += 0x12; + // skip_opcodes; todo may be different in some binary + *data += 0xc; + // unsigned long dt_count = read_skip_dir_table_count(data); + // 0x01011f + *data += 0x3; + uint64_t dt_count = read_skip_leb128(data); + // print_dt(data, dt_count); + for (uint64_t i =0; i < dt_count; i++) { + uint32_t *dst_ptr = (uint32_t *)*data; + *dst_ptr += bias_info->debug_line_str; + *data += 0x4; + } + // 0201 1f02 0f + *data += 0x5; + uint64_t ft_count = read_skip_leb128(data); + for (uint64_t i =0; i< ft_count; i++){ + uint32_t *dst_ptr = (uint32_t *)*data; + *dst_ptr += bias_info->debug_line_str; + *data += 0x4; + skip_leb128(data); + } + modify_line_number_statement(data, end, bias_info); +} + +int modify_debug_line(elf_link_t *elf_link) { elf_file_t *ef; char *temp_path; struct dwarf_bias_info bias_info; foreach_infile(elf_link, ef) { - Elf64_Shdr *di_sec = elf_find_section_by_name(ef, ".debug_info"); + Elf64_Shdr *dl_sec = elf_find_section_by_name(ef, DEBUG_LINE); unsigned long dst_offset = get_new_offset_by_old_offset( - elf_link, ef, di_sec->sh_offset + elf_link, ef, dl_sec->sh_offset ); - void *di_ptr = get_out_ef(elf_link)->data + dst_offset; - prep_bias_info(elf_link, ef, &bias_info); + uint8_t *dl_ptr = get_out_ef(elf_link)->data + dst_offset; temp_path = temp_get_file_name(ef->file_name); Dwarf_Debug dbg = dwarf_init(temp_path); if (!dbg) si_panic("dwarf_init fail, file: %s\n", temp_path); - dwarf_traverse_cu(dbg, di_ptr, &bias_info); + + int res = 0; + Dwarf_Die first_die; + for (;;) { + res = dwarf_get_first_die_of_next_cu(dbg, &first_die); + if (res == DW_DLV_NO_ENTRY) { + /* no entry */ + break; + } + modify_cu_debug_line((unsigned char **)&dl_ptr, &bias_info); + } + dwarf_finish(dbg); + } + return 0; +} + + +uint64_t decode_count_loc_desc(elf_link_t *elf_link, elf_file_t *ef, + uint8_t **optr, struct dwarf_bias_info *bias_info) { + uint64_t cld_len = read_skip_leb128(optr); + uint8_t *end_ptr = *optr + cld_len; + while (*optr < end_ptr) { + uint8_t op = **optr; + ++*optr; + // printf("(%x)", op); + switch (op) + { + case DW_OP_addr: { + old_addr_to_new_skip(optr, elf_link, ef); + // skip_leb128((unsigned char **)&optr); + // optr += read_skip_leb128((unsigned char **)&optr); + break; + } + case DW_OP_deref: + case DW_OP_dup: + case DW_OP_drop: + case DW_OP_over: + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_xderef: + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + case DW_OP_eq: + case DW_OP_ge: + case DW_OP_gt: + case DW_OP_le: + case DW_OP_lt: + case DW_OP_ne: + case DW_OP_lit0: + case DW_OP_lit1: + case DW_OP_lit2: + case DW_OP_lit3: + case DW_OP_lit4: + case DW_OP_lit5: + case DW_OP_lit6: + case DW_OP_lit7: + case DW_OP_lit8: + case DW_OP_lit9: + case DW_OP_lit10: + case DW_OP_lit11: + case DW_OP_lit12: + case DW_OP_lit13: + case DW_OP_lit14: + case DW_OP_lit15: + case DW_OP_lit16: + case DW_OP_lit17: + case DW_OP_lit18: + case DW_OP_lit19: + case DW_OP_lit20: + case DW_OP_lit21: + case DW_OP_lit22: + case DW_OP_lit23: + case DW_OP_lit24: + case DW_OP_lit25: + case DW_OP_lit26: + case DW_OP_lit27: + case DW_OP_lit28: + case DW_OP_lit29: + case DW_OP_lit30: + case DW_OP_lit31: + case DW_OP_reg0: + case DW_OP_reg1: + case DW_OP_reg2: + case DW_OP_reg3: + case DW_OP_reg4: + case DW_OP_reg5: + case DW_OP_reg6: + case DW_OP_reg7: + case DW_OP_reg8: + case DW_OP_reg9: + case DW_OP_reg10: + case DW_OP_reg11: + case DW_OP_reg12: + case DW_OP_reg13: + case DW_OP_reg14: + case DW_OP_reg15: + case DW_OP_reg16: + case DW_OP_reg17: + case DW_OP_reg18: + case DW_OP_reg19: + case DW_OP_reg20: + case DW_OP_reg21: + case DW_OP_reg22: + case DW_OP_reg23: + case DW_OP_reg24: + case DW_OP_reg25: + case DW_OP_reg26: + case DW_OP_reg27: + case DW_OP_reg28: + case DW_OP_reg29: + case DW_OP_reg30: + case DW_OP_reg31: + case DW_OP_nop: + case DW_OP_form_tls_address: + case DW_OP_call_frame_cfa: + case DW_OP_GNU_push_tls_address: + case DW_OP_GNU_uninit: + case DW_OP_HP_is_value: + case DW_OP_HP_fltconst4: + case DW_OP_HP_fltconst8: + case DW_OP_HP_mod_range: + case DW_OP_HP_unmod_range: + case DW_OP_HP_tls: + case DW_OP_PGI_omp_thread_num: + case DW_OP_stack_value: + break; + case DW_OP_const1u: + case DW_OP_const1s: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + *optr += 1; + break; + case DW_OP_const2u: + case DW_OP_const2s: + case DW_OP_bra: + case DW_OP_skip: + *optr += 2; + break; + case DW_OP_const4u: + case DW_OP_const4s: + case DW_OP_GNU_parameter_ref: + *optr += 4; + break; + case DW_OP_const8u: + case DW_OP_const8s: + *optr += 8; + break; + case DW_OP_constu: + case DW_OP_consts: + case DW_OP_breg0: + case DW_OP_breg1: + case DW_OP_breg2: + case DW_OP_breg3: + case DW_OP_breg4: + case DW_OP_breg5: + case DW_OP_breg6: + case DW_OP_breg7: + case DW_OP_breg8: + case DW_OP_breg9: + case DW_OP_breg10: + case DW_OP_breg11: + case DW_OP_breg12: + case DW_OP_breg13: + case DW_OP_breg14: + case DW_OP_breg15: + case DW_OP_breg16: + case DW_OP_breg17: + case DW_OP_breg18: + case DW_OP_breg19: + case DW_OP_breg20: + case DW_OP_breg21: + case DW_OP_breg22: + case DW_OP_breg23: + case DW_OP_breg24: + case DW_OP_breg25: + case DW_OP_breg26: + case DW_OP_breg27: + case DW_OP_breg28: + case DW_OP_breg29: + case DW_OP_breg30: + case DW_OP_breg31: + case DW_OP_regx: + case DW_OP_fbreg: + case DW_OP_piece: + case DW_OP_convert: + case DW_OP_GNU_convert: + case DW_OP_plus_uconst: + skip_leb128(optr); + break; + case DW_OP_bregx: + case DW_OP_bit_piece: + skip_leb128(optr); + skip_leb128(optr); + break; + case DW_OP_implicit_value: + *optr += read_skip_leb128(optr); + break; + case DW_OP_implicit_pointer: + case DW_OP_GNU_implicit_pointer: { + // not support dwarf_version -1 2 + // todo why 00 00 at end 目前只出现在末尾, 且有多余00 00 , 搞清楚为什么 + uint32_t *di_bias = (uint32_t*)*optr; + *di_bias += bias_info->debug_info; + *optr += 4; + skip_leb128(optr); + break; + } + case DW_OP_entry_value: + case DW_OP_GNU_entry_value: { + decode_count_loc_desc(elf_link, ef, optr, bias_info); + break; + } + case DW_OP_push_object_address: + case DW_OP_call2: + case DW_OP_call4: + case DW_OP_call_ref: + si_panic("old dwarf version 2,3 not support\n"); + break; + case DW_OP_GNU_encoded_addr: + case DW_OP_const_type: + case DW_OP_GNU_const_type: + case DW_OP_regval_type: + case DW_OP_GNU_regval_type: + case DW_OP_deref_type: + case DW_OP_GNU_deref_type: + case DW_OP_reinterpret: + case DW_OP_GNU_reinterpret: + case DW_OP_GNU_addr_index: + case DW_OP_GNU_const_index: + case DW_OP_GNU_variable_value: + // todo may need support + si_panic("not support\n"); + break; + default: + si_panic("OP%xOP not support\n", op); + // if (op >= DW_OP_lo_user + // && op <= DW_OP_hi_user) + // printf (_("(User defined location op 0x%x)"), op); + // else + // printf (_("(Unknown location op 0x%x)"), op); + // /* No way to tell where the next op is, so just bail. */ + // return need_frame_base; + break; + } + } + return cld_len; +} + +void modify_debug_rnglists(elf_link_t *elf_link) +{ + for (unsigned int fi=0; fiin_ef_nr; fi++) { + Elf64_Shdr *drl_sec = elf_find_section_by_name(&elf_link->in_efs[fi], DEBUG_RNGLISTS); + unsigned long dst_offset = get_new_offset_by_old_offset( + elf_link, &elf_link->in_efs[fi], drl_sec->sh_offset + ); + uint8_t *start = get_out_ef(elf_link)->data + dst_offset; + uint8_t *end = start + drl_sec->sh_size; + uint8_t *ptr = start; + while (ptr < end) { + // entry_size len(4) + entry_size + uint8_t *entry_end = ptr + 4 + *(uint32_t*)ptr; + // header of entry is 0xc + ptr += 0xc; + while (ptr < entry_end) { + uint8_t rle = *ptr++; + switch (rle) { + case DW_RLE_end_of_list: + break; + case DW_RLE_offset_pair: + skip_leb128(&ptr); + skip_leb128(&ptr); + break; + case DW_RLE_base_address: + old_addr_to_new_skip(&ptr, elf_link, &elf_link->in_efs[fi]); + break; + case DW_RLE_start_end: + old_addr_to_new_skip(&ptr, elf_link, &elf_link->in_efs[fi]); + old_addr_to_new_skip(&ptr, elf_link, &elf_link->in_efs[fi]); + break; + case DW_RLE_start_length: + old_addr_to_new_skip(&ptr, elf_link, &elf_link->in_efs[fi]); + skip_leb128(&ptr); + break; + case DW_RLE_base_addressx: + case DW_RLE_startx_endx: + case DW_RLE_startx_length: + // related to .debug_addr, not support yet + si_panic("not support\n"); + break; + } + } + } + } +} + +void modify_debug_loclists(elf_link_t *elf_link, struct dwarf_bias_info* dbi) +{ + char *temp_path; + + for (unsigned int fi=0; fiin_ef_nr; fi++) { + Elf64_Shdr *dll_sec = elf_find_section_by_name(&elf_link->in_efs[fi], DEBUG_LOCLISTS); + unsigned long dst_offset = get_new_offset_by_old_offset( + elf_link, &elf_link->in_efs[fi], dll_sec->sh_offset + ); + uint8_t *start = get_out_ef(elf_link)->data + dst_offset; + + temp_path = temp_get_file_name(elf_link->in_efs[fi].file_name); + Dwarf_Debug dbg = dwarf_init(temp_path); + if (!dbg) + si_panic("dwarf_init fail, file: %s\n", temp_path); + + for (uint64_t i= 0; i < dbi[fi].lvp.num; i++){ + uint8_t *dll_ptr = start + dbi[fi].lvp.end[i]; + bool end_mark = false; + while (!end_mark) { + uint8_t lle = *dll_ptr++; + // printf("%lx, %x\n", dll_ptr-start-1, lle); + switch (lle) { + case DW_LLE_end_of_list: + end_mark = true; + break; + case DW_LLE_base_address: { + old_addr_to_new_skip(&dll_ptr, elf_link, &elf_link->in_efs[fi]); + break; + } + case DW_LLE_offset_pair: { + skip_leb128(&dll_ptr); + skip_leb128(&dll_ptr); + // uint64_t cld_len = read_skip_leb128(&dll_ptr); + // unsigned int extra_skip = decode_count_loc_desc(elf_link, ef, dll_ptr, cld_len); + // dll_ptr += cld_len; + // dll_ptr += extra_skip; + decode_count_loc_desc(elf_link, &elf_link->in_efs[fi], &dll_ptr, &dbi[fi]); + // dll_ptr += read_skip_leb128(&dll_ptr); + break; + } + case DW_LLE_start_length: { + old_addr_to_new_skip(&dll_ptr, elf_link, &elf_link->in_efs[fi]); + skip_leb128(&dll_ptr); + // unsigned long cld_len = read_skip_leb128((unsigned char **)&dll_ptr); + // unsigned int extra_skip = decode_count_loc_desc(elf_link, ef, dll_ptr, cld_len); + // dll_ptr += cld_len; + // dll_ptr += extra_skip; + // uint64_t aaa = decode_count_loc_desc(elf_link, &elf_link->in_efs[fi], &dll_ptr); + // dll_ptr += aaa; + decode_count_loc_desc(elf_link, &elf_link->in_efs[fi], &dll_ptr, &dbi[fi]); + // dll_ptr += read_skip_leb128(&dll_ptr); + break; + } + default: + si_panic("unknown lle 0x%x\n", lle); + return; + } + } + } + } +} +int modify_debug_info(elf_link_t *elf_link, struct dwarf_bias_info* dbi) +{ + char *temp_path; + + for (unsigned int i=0; iin_ef_nr; i++) { + Elf64_Shdr *di_sec = elf_find_section_by_name(&elf_link->in_efs[i], ".debug_info"); + unsigned long dst_offset = get_new_offset_by_old_offset( + elf_link, &elf_link->in_efs[i], di_sec->sh_offset + ); + void *di_ptr = get_out_ef(elf_link)->data + dst_offset; + + temp_path = temp_get_file_name(elf_link->in_efs[i].file_name); + Dwarf_Debug dbg = dwarf_init(temp_path); + if (!dbg) + si_panic("dwarf_init fail, file: %s\n", temp_path); + dwarf_traverse_cu(dbg, di_ptr, &dbi[i]); dwarf_finish(dbg); } return 0; @@ -1658,7 +2214,12 @@ int modify_debug_info(elf_link_t *elf_link) static void modify_debug(elf_link_t *elf_link) { modify_debug_info_abbrev_offset(elf_link); - modify_debug_info(elf_link); + struct dwarf_bias_info* dbi = init_prep_bias_info(elf_link); + modify_debug_info(elf_link, dbi); + modify_debug_loclists(elf_link, dbi); + modify_debug_rnglists(elf_link); + modify_debug_line(elf_link); + free(dbi); } /* debug modify end */ diff --git a/src/elfmerge/elf_read_elf.c b/src/elfmerge/elf_read_elf.c index 7201aea5be0a8a411e9e450231febffffebc0da7..99b4413ada6dd510c88646c7743a33d1be289ec8 100644 --- a/src/elfmerge/elf_read_elf.c +++ b/src/elfmerge/elf_read_elf.c @@ -539,6 +539,18 @@ bool debug_line_str_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) return strcmp(name, ".debug_line_str") == 0; } +bool debug_loclists_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + return strcmp(name, ".debug_loclists") == 0; +} + +bool debug_rnglists_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) +{ + char *name = elf_get_section_name(ef, sec); + return strcmp(name, ".debug_rnglists") == 0; +} + bool debug_abbrev_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec) { char *name = elf_get_section_name(ef, sec); diff --git a/src/elfmerge/elf_read_elf.h b/src/elfmerge/elf_read_elf.h index 882475329ff92b478aa8b05371e9ce762ea4870b..1c4a50316cbb0411780d0856daf151ace4ca00ca 100644 --- a/src/elfmerge/elf_read_elf.h +++ b/src/elfmerge/elf_read_elf.h @@ -86,6 +86,8 @@ typedef struct { MACRO(SEC_DEBUG_STR, ".debug_str" )\ MACRO(SEC_DEBUG_LINE_STR, ".debug_line_str" )\ MACRO(SEC_DEBUG_ABBREV, ".debug_abbrev" )\ + MACRO(SEC_DEBUG_LOCLISTS, ".debug_loclists" )\ + MACRO(SEC_DEBUG_RNGLISTS, ".debug_rnglists" )\ extern char *needed_sections[]; @@ -421,6 +423,8 @@ bool debug_line_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool debug_str_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool debug_line_str_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool debug_abbrev_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool debug_loclists_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); +bool debug_rnglists_section_filter(const elf_file_t *ef, const Elf64_Shdr *sec); bool elf_is_same_area(const elf_file_t *ef, const Elf64_Shdr *a, const Elf64_Shdr *b); // ELF diff --git a/src/elfmerge/elf_write_elf.c b/src/elfmerge/elf_write_elf.c index 9b9d6a7151065a8a9dd3ca2853afc343cc10bdc0..bb197bbcc0a181bbb434461a7ba0e889de75d13e 100644 --- a/src/elfmerge/elf_write_elf.c +++ b/src/elfmerge/elf_write_elf.c @@ -516,6 +516,8 @@ void merge_debug_sections(elf_link_t *elf_link) merge_filter_sections(elf_link, ".debug_line", debug_line_section_filter); merge_filter_sections(elf_link, ".debug_str", debug_str_section_filter); merge_filter_sections(elf_link, ".debug_line_str", debug_line_str_section_filter); + merge_filter_sections(elf_link, ".debug_loclists", debug_loclists_section_filter); + merge_filter_sections(elf_link, ".debug_rnglists", debug_rnglists_section_filter); } void merge_text_sections(elf_link_t *elf_link)