-
Notifications
You must be signed in to change notification settings - Fork 105
[linux-6.6.y] LoongArch: Fix objtool issues and add jump table feature #609
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Avenger-285714
merged 16 commits into
deepin-community:linux-6.6.y
from
AaronDot:objtool-6.6
Feb 19, 2025
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
bc4229b
compiler.h: specify correct attribute for .rodata..c_jump_table
AaronDot c21344a
objtool: Handle frame pointer related instructions
AaronDot 20a0c21
LoongArch: Add ifdefs to fix LSX and LASX related warnings
AaronDot 61f58c1
LoongArch: Enable objtool for Clang
AaronDot 190fd7c
LoongArch: Set AS_HAS_THIN_ADD_SUB as y if AS_IS_LLVM
AaronDot d4dfe70
objtool: Handle various symbol types of rodata
AaronDot db1750c
objtool: Handle special cases of dead end insn
AaronDot 1e875b4
objtool: Handle different entry size of rodata
AaronDot 4044f63
objtool: Handle PC relative relocation type
AaronDot c2b02f5
objtool: Handle unreachable entry of rodata
AaronDot 2dc8aee
objtool: Handle unsorted table offset of rodata
AaronDot bc1a332
objtool/LoongArch: Get each table size of rodata
AaronDot 01b4d99
objtool/LoongArch: Add support for switch table
AaronDot abc09e6
objtool/LoongArch: Add support for goto table
AaronDot 3fe1189
LoongArch: Enable jump table for objtool
AaronDot 553ae14
LoongArch: Update Loongson-3 config file
AaronDot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
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
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
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
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
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,7 @@ | ||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||
| #include <string.h> | ||
| #include <objtool/special.h> | ||
| #include <objtool/warn.h> | ||
|
|
||
| bool arch_support_alt_relocation(struct special_alt *special_alt, | ||
| struct instruction *insn, | ||
|
|
@@ -8,8 +10,160 @@ bool arch_support_alt_relocation(struct special_alt *special_alt, | |
| return false; | ||
| } | ||
|
|
||
| struct table_info { | ||
| struct list_head jump_info; | ||
| unsigned long insn_offset; | ||
| unsigned long rodata_offset; | ||
| }; | ||
|
|
||
| static void get_rodata_table_size_by_table_annotate(struct objtool_file *file, | ||
| struct instruction *insn) | ||
| { | ||
| struct section *rsec; | ||
| struct reloc *reloc; | ||
| struct list_head table_list; | ||
| struct table_info *orig_table; | ||
| struct table_info *next_table; | ||
| unsigned long tmp_insn_offset; | ||
| unsigned long tmp_rodata_offset; | ||
|
|
||
| rsec = find_section_by_name(file->elf, ".rela.discard.tablejump_annotate"); | ||
| if (!rsec) | ||
| return; | ||
|
|
||
| INIT_LIST_HEAD(&table_list); | ||
|
|
||
| for_each_reloc(rsec, reloc) { | ||
| if (reloc->sym->type != STT_SECTION) | ||
| return; | ||
|
|
||
| orig_table = malloc(sizeof(struct table_info)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (bug_risk): Potential memory leak with allocated table_info objects. The allocated table_info structures are added into the local list but never freed after computing table_size. Consider freeing these allocations before the function returns. |
||
| if (!orig_table) { | ||
| WARN("malloc failed"); | ||
| return; | ||
| } | ||
|
|
||
| orig_table->insn_offset = reloc_addend(reloc); | ||
| reloc++; | ||
| orig_table->rodata_offset = reloc_addend(reloc); | ||
|
|
||
| list_add_tail(&orig_table->jump_info, &table_list); | ||
|
|
||
| if (reloc_idx(reloc) + 1 == sec_num_entries(rsec)) | ||
| break; | ||
| } | ||
|
|
||
| list_for_each_entry(orig_table, &table_list, jump_info) { | ||
| next_table = list_next_entry(orig_table, jump_info); | ||
| list_for_each_entry_from(next_table, &table_list, jump_info) { | ||
| if (next_table->rodata_offset < orig_table->rodata_offset) { | ||
| tmp_insn_offset = next_table->insn_offset; | ||
| tmp_rodata_offset = next_table->rodata_offset; | ||
| next_table->insn_offset = orig_table->insn_offset; | ||
| next_table->rodata_offset = orig_table->rodata_offset; | ||
| orig_table->insn_offset = tmp_insn_offset; | ||
| orig_table->rodata_offset = tmp_rodata_offset; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| list_for_each_entry(orig_table, &table_list, jump_info) { | ||
| if (insn->offset == orig_table->insn_offset) { | ||
| next_table = list_next_entry(orig_table, jump_info); | ||
| if (&next_table->jump_info == &table_list) | ||
| break; | ||
|
|
||
| while (next_table->rodata_offset == orig_table->rodata_offset) | ||
| next_table = list_next_entry(next_table, jump_info); | ||
|
|
||
| insn->table_size = next_table->rodata_offset - orig_table->rodata_offset; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| static struct reloc *find_reloc_by_table_annotate(struct objtool_file *file, | ||
| struct instruction *insn) | ||
| { | ||
| struct section *rsec; | ||
| struct reloc *reloc; | ||
| unsigned long offset; | ||
|
|
||
| rsec = find_section_by_name(file->elf, ".rela.discard.tablejump_annotate"); | ||
| if (!rsec) | ||
| return NULL; | ||
|
|
||
| for_each_reloc(rsec, reloc) { | ||
| if (reloc->sym->sec->rodata) | ||
| continue; | ||
|
|
||
| if (strcmp(insn->sec->name, reloc->sym->sec->name)) | ||
| continue; | ||
|
|
||
| if (reloc->sym->type == STT_SECTION) | ||
| offset = reloc_addend(reloc); | ||
| else | ||
| offset = reloc->sym->offset; | ||
|
|
||
| if (insn->offset == offset) { | ||
| get_rodata_table_size_by_table_annotate(file, insn); | ||
| reloc++; | ||
| return reloc; | ||
| } | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| static struct reloc *find_reloc_of_rodata_c_jump_table(struct section *sec, | ||
| unsigned long offset) | ||
| { | ||
| struct section *rsec; | ||
| struct reloc *reloc; | ||
|
|
||
| rsec = sec->rsec; | ||
| if (!rsec) | ||
| return NULL; | ||
|
|
||
| for_each_reloc(rsec, reloc) { | ||
| if (reloc_offset(reloc) > offset) | ||
| break; | ||
|
|
||
| if (!strncmp(reloc->sym->sec->name, ".rodata..c_jump_table", 21)) | ||
| return reloc; | ||
| } | ||
|
|
||
| return NULL; | ||
| } | ||
|
|
||
| struct reloc *arch_find_switch_table(struct objtool_file *file, | ||
| struct instruction *insn) | ||
| { | ||
| return NULL; | ||
| struct reloc *annotate_reloc; | ||
| struct reloc *rodata_reloc; | ||
| struct section *table_sec; | ||
| unsigned long table_offset; | ||
|
|
||
| annotate_reloc = find_reloc_by_table_annotate(file, insn); | ||
| if (!annotate_reloc) { | ||
| annotate_reloc = find_reloc_of_rodata_c_jump_table(insn->sec, insn->offset); | ||
| if (!annotate_reloc) | ||
| return NULL; | ||
| } | ||
|
|
||
| table_sec = annotate_reloc->sym->sec; | ||
| if (annotate_reloc->sym->type == STT_SECTION) | ||
| table_offset = reloc_addend(annotate_reloc); | ||
| else | ||
| table_offset = annotate_reloc->sym->offset; | ||
|
|
||
| /* | ||
| * Each table entry has a rela associated with it. The rela | ||
| * should reference text in the same function as the original | ||
| * instruction. | ||
| */ | ||
| rodata_reloc = find_reloc_by_dest(file->elf, table_sec, table_offset); | ||
| if (!rodata_reloc) | ||
| return NULL; | ||
|
|
||
| return rodata_reloc; | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider extracting the nested sorting logic into a dedicated helper function.
Consider extracting the nested sorting logic into its own routine to eliminate the duplicated pointer arithmetic and deeply nested loops. For example, if you have a list sort helper available (or can add one), you could write a dedicated comparator and sort routine:
Then update the function to delegate the sorting:
This separation increases clarity, isolates pointer arithmetic, and makes the control flow easier to follow while keeping the functionality intact.