[tip:core/objtool] objtool: Support per-function rodata sections

2018-09-08 Thread tip-bot for Allan Xavier
Commit-ID:  4a60aa05a0634241ce17f957bf9fb5ac1eed6576
Gitweb: https://git.kernel.org/tip/4a60aa05a0634241ce17f957bf9fb5ac1eed6576
Author: Allan Xavier 
AuthorDate: Fri, 7 Sep 2018 08:12:01 -0500
Committer:  Thomas Gleixner 
CommitDate: Sat, 8 Sep 2018 12:33:01 +0200

objtool: Support per-function rodata sections

Add support for processing switch jump tables in objects with multiple
.rodata sections, such as those created by '-ffunction-sections' and
'-fdata-sections'.  Currently, objtool always looks in .rodata for jump
table information, which results in many "sibling call from callable
instruction with modified stack frame" warnings with objects compiled
using those flags.

The fix is comprised of three parts:

1. Flagging all .rodata sections when importing ELF information for
   easier checking later.

2. Keeping a reference to the section each relocation is from in order
   to get the list_head for the other relocations in that section.

3. Finding jump tables by following relocations to .rodata sections,
   rather than always referencing a single global .rodata section.

The patch has been tested without data sections enabled and no
differences in the resulting orc unwind information were seen.

Note that as objtool adds terminators to end of each .text section the
unwind information generated between a function+data sections build and
a normal build aren't directly comparable. Manual inspection suggests
that objtool is now generating the correct information, or at least
making more of an effort to do so than it did previously.

Signed-off-by: Allan Xavier 
Signed-off-by: Josh Poimboeuf 
Signed-off-by: Thomas Gleixner 
Link: 
https://lkml.kernel.org/r/099bdc375195c490dda04db777ee0b95d566ded1.1536325914.git.jpoim...@redhat.com

---
 tools/objtool/check.c | 38 --
 tools/objtool/check.h |  4 ++--
 tools/objtool/elf.c   |  1 +
 tools/objtool/elf.h   |  3 ++-
 4 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 2928939b98ec..0414a0d52262 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -836,7 +836,7 @@ static int add_switch_table(struct objtool_file *file, 
struct instruction *insn,
struct symbol *pfunc = insn->func->pfunc;
unsigned int prev_offset = 0;
 
-   list_for_each_entry_from(rela, >rodata->rela->rela_list, list) {
+   list_for_each_entry_from(rela, >rela_sec->rela_list, list) {
if (rela == next_table)
break;
 
@@ -926,6 +926,7 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
 {
struct rela *text_rela, *rodata_rela;
struct instruction *orig_insn = insn;
+   struct section *rodata_sec;
unsigned long table_offset;
 
/*
@@ -953,10 +954,13 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
/* look for a relocation which references .rodata */
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
insn->len);
-   if (!text_rela || text_rela->sym != file->rodata->sym)
+   if (!text_rela || text_rela->sym->type != STT_SECTION ||
+   !text_rela->sym->sec->rodata)
continue;
 
table_offset = text_rela->addend;
+   rodata_sec = text_rela->sym->sec;
+
if (text_rela->type == R_X86_64_PC32)
table_offset += 4;
 
@@ -964,10 +968,10 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
 * Make sure the .rodata address isn't associated with a
 * symbol.  gcc jump tables are anonymous data.
 */
-   if (find_symbol_containing(file->rodata, table_offset))
+   if (find_symbol_containing(rodata_sec, table_offset))
continue;
 
-   rodata_rela = find_rela_by_dest(file->rodata, table_offset);
+   rodata_rela = find_rela_by_dest(rodata_sec, table_offset);
if (rodata_rela) {
/*
 * Use of RIP-relative switch jumps is quite rare, and
@@ -1052,7 +1056,7 @@ static int add_switch_table_alts(struct objtool_file 
*file)
struct symbol *func;
int ret;
 
-   if (!file->rodata || !file->rodata->rela)
+   if (!file->rodata)
return 0;
 
for_each_sec(file, sec) {
@@ -1198,10 +1202,33 @@ static int read_retpoline_hints(struct objtool_file 
*file)
return 0;
 }
 
+static void mark_rodata(struct objtool_file *file)
+{
+   struct section *sec;
+   bool found = false;
+
+   /*
+* This searches for the .rodata section or multiple .rodata.func_name
+* sections if -fdata-sections is being used. The .str.1.1 and .str.1.8
+* rodata sections are ignored as they don't contain jump tables.
+ 

[tip:core/objtool] objtool: Support per-function rodata sections

2018-09-08 Thread tip-bot for Allan Xavier
Commit-ID:  4a60aa05a0634241ce17f957bf9fb5ac1eed6576
Gitweb: https://git.kernel.org/tip/4a60aa05a0634241ce17f957bf9fb5ac1eed6576
Author: Allan Xavier 
AuthorDate: Fri, 7 Sep 2018 08:12:01 -0500
Committer:  Thomas Gleixner 
CommitDate: Sat, 8 Sep 2018 12:33:01 +0200

objtool: Support per-function rodata sections

Add support for processing switch jump tables in objects with multiple
.rodata sections, such as those created by '-ffunction-sections' and
'-fdata-sections'.  Currently, objtool always looks in .rodata for jump
table information, which results in many "sibling call from callable
instruction with modified stack frame" warnings with objects compiled
using those flags.

The fix is comprised of three parts:

1. Flagging all .rodata sections when importing ELF information for
   easier checking later.

2. Keeping a reference to the section each relocation is from in order
   to get the list_head for the other relocations in that section.

3. Finding jump tables by following relocations to .rodata sections,
   rather than always referencing a single global .rodata section.

The patch has been tested without data sections enabled and no
differences in the resulting orc unwind information were seen.

Note that as objtool adds terminators to end of each .text section the
unwind information generated between a function+data sections build and
a normal build aren't directly comparable. Manual inspection suggests
that objtool is now generating the correct information, or at least
making more of an effort to do so than it did previously.

Signed-off-by: Allan Xavier 
Signed-off-by: Josh Poimboeuf 
Signed-off-by: Thomas Gleixner 
Link: 
https://lkml.kernel.org/r/099bdc375195c490dda04db777ee0b95d566ded1.1536325914.git.jpoim...@redhat.com

---
 tools/objtool/check.c | 38 --
 tools/objtool/check.h |  4 ++--
 tools/objtool/elf.c   |  1 +
 tools/objtool/elf.h   |  3 ++-
 4 files changed, 37 insertions(+), 9 deletions(-)

diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 2928939b98ec..0414a0d52262 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -836,7 +836,7 @@ static int add_switch_table(struct objtool_file *file, 
struct instruction *insn,
struct symbol *pfunc = insn->func->pfunc;
unsigned int prev_offset = 0;
 
-   list_for_each_entry_from(rela, >rodata->rela->rela_list, list) {
+   list_for_each_entry_from(rela, >rela_sec->rela_list, list) {
if (rela == next_table)
break;
 
@@ -926,6 +926,7 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
 {
struct rela *text_rela, *rodata_rela;
struct instruction *orig_insn = insn;
+   struct section *rodata_sec;
unsigned long table_offset;
 
/*
@@ -953,10 +954,13 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
/* look for a relocation which references .rodata */
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
insn->len);
-   if (!text_rela || text_rela->sym != file->rodata->sym)
+   if (!text_rela || text_rela->sym->type != STT_SECTION ||
+   !text_rela->sym->sec->rodata)
continue;
 
table_offset = text_rela->addend;
+   rodata_sec = text_rela->sym->sec;
+
if (text_rela->type == R_X86_64_PC32)
table_offset += 4;
 
@@ -964,10 +968,10 @@ static struct rela *find_switch_table(struct objtool_file 
*file,
 * Make sure the .rodata address isn't associated with a
 * symbol.  gcc jump tables are anonymous data.
 */
-   if (find_symbol_containing(file->rodata, table_offset))
+   if (find_symbol_containing(rodata_sec, table_offset))
continue;
 
-   rodata_rela = find_rela_by_dest(file->rodata, table_offset);
+   rodata_rela = find_rela_by_dest(rodata_sec, table_offset);
if (rodata_rela) {
/*
 * Use of RIP-relative switch jumps is quite rare, and
@@ -1052,7 +1056,7 @@ static int add_switch_table_alts(struct objtool_file 
*file)
struct symbol *func;
int ret;
 
-   if (!file->rodata || !file->rodata->rela)
+   if (!file->rodata)
return 0;
 
for_each_sec(file, sec) {
@@ -1198,10 +1202,33 @@ static int read_retpoline_hints(struct objtool_file 
*file)
return 0;
 }
 
+static void mark_rodata(struct objtool_file *file)
+{
+   struct section *sec;
+   bool found = false;
+
+   /*
+* This searches for the .rodata section or multiple .rodata.func_name
+* sections if -fdata-sections is being used. The .str.1.1 and .str.1.8
+* rodata sections are ignored as they don't contain jump tables.
+