[PATCH v5 05/10] objtool/LoongArch: Add support for switch table

Tiezhu Yang posted 10 patches 1 year ago
There is a newer version of this series
[PATCH v5 05/10] objtool/LoongArch: Add support for switch table
Posted by Tiezhu Yang 1 year ago
The objtool program need to analysis the control flow of each object file
generated by compiler toolchain, it needs to know all the locations that
a branch instruction may jump into, if a jump table is used, objtool has
to correlate the jump instruction with the table.

On x86 (which is the only port supported by objtool before LoongArch),
there is a relocation type on the jump instruction and directly points
to the table. But on LoongArch, the relocation is on another kind of
instruction prior to the jump instruction, and also with scheduling it
is not very easy to tell the offset of that instruction from the jump
instruction. Furthermore, because LoongArch has -fsection-anchors (often
enabled at -O1 or above) the relocation may actually points to a section
anchor instead of the table itself.

The good news is that after continuous analysis and discussion, at last
a GCC patch "LoongArch: Add support to annotate tablejump" and a Clang
patch "[LoongArch] Add options for annotate tablejump" have been merged
into the upstream mainline, the compiler changes make life much easier
for switch table support of objtool on LoongArch.

By now, there is an additional section ".discard.tablejump_annotate" to
store the jump info as pairs of addresses, each pair contains the address
of jump instruction and the address of jump table.

In order to find switch table, it is easy to parse the relocation section
".rela.discard.tablejump_annotate" to get table_sec and table_offset, the
rest process is somehow like x86.

Link: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=0ee028f55640
Link: https://github.com/llvm/llvm-project/commit/4c2c17756739
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
 tools/objtool/arch/loongarch/special.c | 53 +++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

diff --git a/tools/objtool/arch/loongarch/special.c b/tools/objtool/arch/loongarch/special.c
index 87230ed570fd..f933f6b5bac6 100644
--- a/tools/objtool/arch/loongarch/special.c
+++ b/tools/objtool/arch/loongarch/special.c
@@ -1,4 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
+#include <string.h>
 #include <objtool/special.h>
 
 bool arch_support_alt_relocation(struct special_alt *special_alt,
@@ -8,9 +9,59 @@ bool arch_support_alt_relocation(struct special_alt *special_alt,
 	return false;
 }
 
+static struct reloc *find_reloc_by_table_annotate(struct objtool_file *file,
+						  struct instruction *insn,
+						  unsigned long *table_size)
+{
+	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;
+
+		offset = reloc->sym->offset + reloc_addend(reloc);
+		if (insn->offset == offset) {
+			reloc++;
+			return reloc;
+		}
+	}
+
+	return NULL;
+}
+
 struct reloc *arch_find_switch_table(struct objtool_file *file,
 				     struct instruction *insn,
 				     unsigned long *table_size)
 {
-	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, table_size);
+	if (!annotate_reloc)
+		return NULL;
+
+	table_sec = annotate_reloc->sym->sec;
+	table_offset = annotate_reloc->sym->offset + reloc_addend(annotate_reloc);
+
+	/*
+	 * 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;
 }
-- 
2.42.0
Re: [PATCH v5 05/10] objtool/LoongArch: Add support for switch table
Posted by Josh Poimboeuf 1 year ago
On Sat, Dec 07, 2024 at 09:59:10AM +0800, Tiezhu Yang wrote:
>  struct reloc *arch_find_switch_table(struct objtool_file *file,
>  				     struct instruction *insn,
>  				     unsigned long *table_size)
>  {

This seems to be a partial implementation as it doesn't set
'table_size', resulting in undefined behavior when the size gets used by
objtool later.   I suppose this patch should be squashed with the next
one?

-- 
Josh
Re: [PATCH v5 05/10] objtool/LoongArch: Add support for switch table
Posted by Tiezhu Yang 1 year ago
On 12/10/2024 04:39 AM, Josh Poimboeuf wrote:
> On Sat, Dec 07, 2024 at 09:59:10AM +0800, Tiezhu Yang wrote:
>>  struct reloc *arch_find_switch_table(struct objtool_file *file,
>>  				     struct instruction *insn,
>>  				     unsigned long *table_size)
>>  {
>
> This seems to be a partial implementation as it doesn't set
> 'table_size', resulting in undefined behavior when the size gets used by
> objtool later.   I suppose this patch should be squashed with the next
> one?

OK, makes sense, I will squash them into one single patch.

Let me wait for some days, if no more comments, I will send v6
in the next week.

Thanks,
Tiezhu