Created
January 13, 2026 16:56
-
-
Save jmontleon/f57b7a2d282d64a4479cff094a94306c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/tools/debugedit.c b/tools/debugedit.c | |
| index c7cd778..96dc96d 100644 | |
| --- a/tools/debugedit.c | |
| +++ b/tools/debugedit.c | |
| @@ -2846,6 +2846,77 @@ edit_dwarf2_any_str (DSO *dso, struct strings *strings, debug_section *secp) | |
| elf_flagdata (strdata, ELF_C_SET, ELF_F_DIRTY); | |
| } | |
| +/* Update symbol table entries that reference modified debug string sections. | |
| + When we modify .debug_str or .debug_line_str sections, symbols that point | |
| + into these sections need their st_value updated to reflect the new offsets. | |
| + This is particularly important for RISC-V and other architectures that use | |
| + local symbols to reference string section offsets. Without this update, | |
| + symbols can point beyond the end of the section after it has been shrunk, | |
| + causing linker errors and corrupt DWARF information. */ | |
| +static void | |
| +update_symtab_for_debug_str_changes (DSO *dso) | |
| +{ | |
| + /* Find the symbol table section(s) */ | |
| + for (int i = 1; i < dso->ehdr.e_shnum; ++i) | |
| + { | |
| + if (dso->shdr[i].sh_type == SHT_SYMTAB) | |
| + { | |
| + Elf_Scn *scn = dso->scn[i]; | |
| + Elf_Data *symdata = elf_getdata (scn, NULL); | |
| + if (symdata == NULL) | |
| + continue; | |
| + | |
| + int symcount = dso->shdr[i].sh_size / dso->shdr[i].sh_entsize; | |
| + bool modified = false; | |
| + | |
| + for (int j = 0; j < symcount; j++) | |
| + { | |
| + GElf_Sym sym; | |
| + if (gelf_getsym (symdata, j, &sym) == NULL) | |
| + continue; | |
| + | |
| + /* Check if this symbol references a modified debug string section */ | |
| + struct strings *strings = NULL; | |
| + if (need_strp_update | |
| + && sym.st_shndx == debug_sections[DEBUG_STR].sec) | |
| + strings = &dso->debug_str; | |
| + else if (need_line_strp_update | |
| + && sym.st_shndx == debug_sections[DEBUG_LINE_STR].sec) | |
| + strings = &dso->debug_line_str; | |
| + | |
| + if (strings != NULL) | |
| + { | |
| + /* Look up the old offset to find the new one */ | |
| + size_t old_offset = sym.st_value; | |
| + struct stridxentry *entry = string_find_entry (strings, | |
| + old_offset, | |
| + true); | |
| + | |
| + /* If we found the entry, update the symbol */ | |
| + if (entry != &debugedit_stridxentry) | |
| + { | |
| + size_t new_offset = strent_offset (entry->entry); | |
| + if (new_offset != old_offset) | |
| + { | |
| + sym.st_value = new_offset; | |
| + if (gelf_update_sym (symdata, j, &sym) == 0) | |
| + error (1, 0, "Failed to update symbol: %s", | |
| + elf_errmsg (-1)); | |
| + modified = true; | |
| + } | |
| + } | |
| + } | |
| + } | |
| + | |
| + if (modified) | |
| + elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY); | |
| + | |
| + /* There's typically only one symbol table, but we'll continue | |
| + checking in case there are multiple */ | |
| + } | |
| + } | |
| +} | |
| + | |
| /* Rebuild .debug_str_offsets. */ | |
| static void | |
| update_str_offsets (DSO *dso) | |
| @@ -3358,6 +3429,12 @@ edit_dwarf2 (DSO *dso) | |
| if (phase == 0 && need_line_strp_update) | |
| edit_dwarf2_any_str (dso, &dso->debug_line_str, | |
| &debug_sections[DEBUG_LINE_STR]); | |
| + | |
| + /* After modifying string sections, update any symbols that reference them. | |
| + This is critical for RISC-V and other architectures that use local | |
| + symbols to reference offsets within mergeable string sections. */ | |
| + if (phase == 0 && (need_strp_update || need_line_strp_update)) | |
| + update_symtab_for_debug_str_changes (dso); | |
| } | |
| /* After phase 1 we might have rewritten the debug_info with |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment