diff --git a/Makefile b/Makefile index d0ac45571f4e5fca1b7d60d23a14667c0a2e64e3..2f4289ebee527063da4665660401861d6497ab8c 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,10 @@ install: xz -k $(BUILD_DIR)/src/static_template/sysboost_static_template mv -f $(BUILD_DIR)/src/static_template/sysboost_static_template.xz /usr/lib/relocation/ +# .debug_* in sysboost_static_template and sysboost_static_template.relocation are not same, need sync +sync_tmp: + xz -k build/src/static_template/sysboost_static_template -c > /usr/lib/relocation/sysboost_static_template.relocation + test: sysboostd install clear ./tests/test_sysboostd.py diff --git a/src/elfmerge/elf_link_common.c b/src/elfmerge/elf_link_common.c index ee2a8fa1fc8d2926f38c1a2bf524825b7f2cd6d4..ba691745cc9963cad6f0f998bec78363faf8059a 100644 --- a/src/elfmerge/elf_link_common.c +++ b/src/elfmerge/elf_link_common.c @@ -128,6 +128,8 @@ static char *needed_sections[] = { ".debug_str", ".debug_line_str", ".debug_abbrev", + ".debug_loclists", + ".debug_rnglists" }; #define NEEDED_SECTIONS_LEN (sizeof(needed_sections) / sizeof(needed_sections[0])) diff --git a/src/elfmerge/elf_link_elf.c b/src/elfmerge/elf_link_elf.c index 778f55e1e44de85503bc3f11f587c6077fadeb95..5f2cd817bf127b7508911755f95bdeb05ad3f985 100644 --- a/src/elfmerge/elf_link_elf.c +++ b/src/elfmerge/elf_link_elf.c @@ -1435,6 +1435,9 @@ 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; }; int dwarf_modify_di_abbrev(Dwarf_Die die, void *di_ptr, struct dwarf_bias_info *bias_info) @@ -1498,15 +1501,33 @@ 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: + // DW_AT_location...??? case DW_FORM_exprloc: case DW_FORM_flag_present: + // DW_AT_stmt_list: debug_line, ... more case DW_FORM_sec_offset: /* TODO */ + switch (die->di_abbrev_list->abl_attr[i]){ + case DW_AT_stmt_list: + *dst_ptr += bias_info->debug_line; + break; + // case DW_AT_ranges: + // *dst_ptr += bias_info->debug_rnglists; + // break; + // case DW_AT_location: + // case DW_AT_GNU_locviews: + // *dst_ptr += bias_info->debug_loclists; + // break; + } break; case DW_FORM_block4: case DW_FORM_block: @@ -1606,6 +1627,12 @@ void prep_bias_info(elf_link_t *elf_link, elf_file_t *ef, struct dwarf_bias_info 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; + unsigned long dl_base_offset = + elf_find_section_by_name(get_out_ef(elf_link), ".debug_line")->sh_offset; + unsigned long dll_base_offset = + elf_find_section_by_name(get_out_ef(elf_link), ".debug_loclists")->sh_offset; + unsigned long drl_base_offset = + elf_find_section_by_name(get_out_ef(elf_link), ".debug_rnglists")->sh_offset; Elf64_Shdr *text_sec = elf_find_section_by_name(ef, ".init"); unsigned long text_addr = get_new_addr_by_old_addr( @@ -1619,10 +1646,25 @@ void prep_bias_info(elf_link_t *elf_link, elf_file_t *ef, struct dwarf_bias_info unsigned long dls_offset = get_new_offset_by_old_offset( elf_link, ef, dls_sec->sh_offset ); + Elf64_Shdr *dl_sec = elf_find_section_by_name(ef, ".debug_line"); + unsigned long dl_offset = get_new_offset_by_old_offset( + elf_link, ef, dl_sec->sh_offset + ); + Elf64_Shdr *dll_sec = elf_find_section_by_name(ef, ".debug_loclists"); + unsigned long dll_offset = get_new_offset_by_old_offset( + elf_link, ef, dll_sec->sh_offset + ); + Elf64_Shdr *drl_sec = elf_find_section_by_name(ef, ".debug_rnglists"); + unsigned long drl_offset = get_new_offset_by_old_offset( + elf_link, ef, drl_sec->sh_offset + ); 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; + bias_info->debug_line = dl_offset - dl_base_offset; + bias_info->debug_loclists = dll_offset - dll_base_offset; + bias_info->debug_rnglists = drl_offset - drl_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); @@ -1630,6 +1672,267 @@ void prep_bias_info(elf_link_t *elf_link, elf_file_t *ef, struct dwarf_bias_info text_addr, text_base_addr); } +void skip_leb128(unsigned char** data){ + printf(".(%p,%02x)", (void*)*data, **data&0xff); + while (**data & 0x80) { + ++*data; + printf("(%p,%02x)", (void*)*data, **data&0xff); + } + ++*data; + printf("-(%p,%02x)", (void*)*data, **data&0xff); +} + +unsigned long read_skip_leb128(unsigned char** data) { + unsigned long result = 0; + unsigned int shift = 0; + unsigned char byte; + + do { + byte = **data; + ++*data; + result |= (byte & 0x7f) << shift; + shift += 7; + } while (byte & 0x80); + + return result; +} + +void process_extended_line_op( + // unsigned char * start, + unsigned char ** data, + struct dwarf_bias_info *bias_info + ) +{ + // *data++; + // LEB128 is mentioned in the document, but use byte actually, because max op_code is 0x80 + unsigned long len = read_skip_leb128(data); + unsigned char op_code = **data; + // printf("(%lx)", **data); + ++*data; + // printf("(%lx)", **data); + printf("[%x]:len:%lx", op_code, len); + uint32_t *dst_ptr = (uint32_t *)*data; + switch (op_code) { + case DW_LNE_end_sequence: + printf ("DW_LNE_end_sequence\n"); + break; + case DW_LNE_set_address: + *dst_ptr += bias_info->text; + // printf("(%lx)", **data); + // unsigned long *addr = (unsigned long*) *data; + printf("=== %lx, %lx \n", (unsigned long) *data, bias_info->text); + break; + case DW_LNE_define_file: + //The DW_LNE_define_file operation defined in earlier versions of DWARF is deprecated 5 in DWARF Version 5. + printf ("DW_LNE_define_file\n"); + break; + + case DW_LNE_set_discriminator: + // set dir path? no need to modify? + // skip_leb128(data); + printf ("set Discriminator\n"); + break; + + /* HP extensions. */ + case DW_LNE_HP_negate_is_UV_update: + printf ("DW_LNE_HP_negate_is_UV_update\n"); + break; + case DW_LNE_HP_push_context: + printf ("DW_LNE_HP_push_context\n"); + break; + case DW_LNE_HP_pop_context: + printf ("DW_LNE_HP_pop_context\n"); + break; + case DW_LNE_HP_set_file_line_column: + printf ("DW_LNE_HP_set_file_line_column\n"); + break; + case DW_LNE_HP_set_routine_name: + printf ("DW_LNE_HP_set_routine_name\n"); + break; + case DW_LNE_HP_set_sequence: + printf ("DW_LNE_HP_set_sequence\n"); + break; + case DW_LNE_HP_negate_post_semantics: + printf ("DW_LNE_HP_negate_post_semantics\n"); + break; + case DW_LNE_HP_negate_function_exit: + printf ("DW_LNE_HP_negate_function_exit\n"); + break; + case DW_LNE_HP_negate_front_end_logical: + printf ("DW_LNE_HP_negate_front_end_logical\n"); + break; + case DW_LNE_HP_define_proc: + printf ("DW_LNE_HP_define_proc\n"); + break; + // case DW_LNE_HP_source_file_correlation: + // // no common? raise error if occur + // break; + + default: + { + printf("UNKNOWN extended_line_op ERROR\n"); + exit(1); + } + } + *data += len - 1; +} + +static void modify_line_number_statement( + unsigned char ** data, unsigned char *start, unsigned char *end, + struct dwarf_bias_info *bias_info) +{ + // int cu_line_offset = 0x1b5; + // unsigned char *start = *data - cu_line_offset; + while (*data < end){ //ptr < end + unsigned char op_code; + printf("%lx ", *data-start); + op_code = **data; + ++*data; + printf("OP[%x]:", op_code); + switch (op_code) + { + // DW_LNS_extended_op + case 0: + process_extended_line_op(data, bias_info); + // if (*(unsigned short*)*data == 0x0101){ + // *data += 0x2; + // printf("DW_LNE_end_sequence\n"); + // return 0; + // } + // else { + // process_extended_line_op(data); + // } + break; + case DW_LNS_copy: + printf("DW_LNS_copy\n"); + break; + case DW_LNS_advance_pc: + printf("DW_LNS_advance_pc\n"); + skip_leb128(data); + break; + case DW_LNS_advance_line: + printf("DW_LNS_advance_line\n"); + /* + [0x00000bcc] Extended opcode 1: End of Sequence + + [0x00000bcf] Set column to 1 bb1 OP[3]:DW_LNS_advance_line +.(0xffff8bc19baf,a7)(0xffff8bc19bb0,71)-(0xffff8bc19bb1,4a)bb4 OP[4a]:Sp_op 61 +*/ + skip_leb128(data); + break; + case DW_LNS_set_file: + printf("\n"); + skip_leb128(data); + break; + case DW_LNS_set_column: + skip_leb128(data); + printf("DW_LNS_set_column: skip\n"); + break; + case DW_LNS_negate_stmt: + printf("DW_LNS_negate_stmt\n"); + break; + case DW_LNS_set_basic_block: + printf("DW_LNS_set_basic_block\n"); + break; + case DW_LNS_const_add_pc: + printf("\n"); + break; + case DW_LNS_fixed_advance_pc: + printf("\n"); + // nead process, but this op only use in few machine + break; + case DW_LNS_set_prologue_end: + printf("\n"); + break; + case DW_LNS_set_epilogue_begin: + printf("\n"); + break; + case DW_LNS_set_isa: + skip_leb128(data); + break; + + default: + printf("Sp_op %d\n", (op_code-13)); + // printf("NT YT\n"); + // exit(2); + } + // return 0; + } +} + +void modify_cu_debug_line(unsigned char ** data, struct dwarf_bias_info *bias_info, unsigned char *start)//, int cu_num) +{ + // unsigned int cu_dl_len = *(int *)data; + unsigned char *end = *(int *)*data + *data + 0x4; + printf("\n***modify_cu_debug_line***%ld***\n", end - start); + // skip_header(data); + *data += 0x12; + // skip_opcodes(data); + *data += 0xc; + // unsigned long dt_count = read_skip_dir_table_count(data); + // 0x01011f + *data += 0x3; + unsigned long dt_count = read_skip_leb128(data); + // print_dt(data, dt_count); + for (unsigned long i =0; i < dt_count; i++){ + printf("%ld,%x:%x\n", i, *(unsigned int*)*data, *(unsigned int*)*data); + uint32_t *dst_ptr = (uint32_t *)*data; + *dst_ptr += bias_info->debug_line_str; + // **data += bias_info->debug_line_str; + *data += 4; + } + // unsigned long ft_count = read_skip_file_name_table_count(data); + // 0201 1f02 0f + *data += 0x5; + unsigned long ft_count = read_skip_leb128(data); + // print_ft(data, ft_count); + for (unsigned long i =0; i< ft_count; i++){ + printf("%ld,%x:%x\n", i, *(unsigned int*)*data, *(unsigned int*)*data); + // **data += bias_info->debug_line_str; + uint32_t *dst_ptr = (uint32_t *)*data; + *dst_ptr += bias_info->debug_line_str; + *data += 4; + skip_leb128(data); + } + modify_line_number_statement(data, start, end, bias_info); + // exit(1); +} + +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 *dl_sec = elf_find_section_by_name(ef, ".debug_line"); + unsigned long dst_offset = get_new_offset_by_old_offset( + elf_link, ef, dl_sec->sh_offset + ); + void *dl_ptr = get_out_ef(elf_link)->data + dst_offset; + unsigned char *start = dl_ptr; + prep_bias_info(elf_link, ef, &bias_info); + + 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); + + 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, start); + } + dwarf_finish(dbg); + } + return 0; +} + int modify_debug_info(elf_link_t *elf_link) { elf_file_t *ef; @@ -1654,10 +1957,13 @@ int modify_debug_info(elf_link_t *elf_link) return 0; } + static void modify_debug(elf_link_t *elf_link) { modify_debug_info_abbrev_offset(elf_link); modify_debug_info(elf_link); + modify_debug_line(elf_link); + // todo modify_debug_list(elf_link); } /* debug modify end */ diff --git a/src/elfmerge/elf_read_elf.c b/src/elfmerge/elf_read_elf.c index d27f1bf9373d5d0cc8766a5b47e69b60ee1367ba..5e2d2f8a8566b7096becf88ac7951d56ee166323 100644 --- a/src/elfmerge/elf_read_elf.c +++ b/src/elfmerge/elf_read_elf.c @@ -523,6 +523,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 98b747664df40c194d681b453d58c583a810861a..b2885bb31ae8932a791d675c1a17848fed5e9b77 100644 --- a/src/elfmerge/elf_read_elf.h +++ b/src/elfmerge/elf_read_elf.h @@ -360,6 +360,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)