summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/checkpatch.pl166
-rw-r--r--scripts/docproc.c14
-rw-r--r--scripts/gen_initramfs_list.sh24
-rwxr-xr-xscripts/kernel-doc6
-rw-r--r--scripts/mod/modpost.c15
-rw-r--r--scripts/sortextable.c24
-rw-r--r--scripts/sortextable.h26
7 files changed, 205 insertions, 70 deletions
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 66cad50..61090e0 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -241,8 +241,11 @@ our $Sparse = qr{
__ref|
__rcu
}x;
-
-our $InitAttribute = qr{__(?:mem|cpu|dev|net_|)(?:initdata|initconst|init\b)};
+our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)};
+our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)};
+our $InitAttributeConst = qr{$InitAttributePrefix(?:initconst\b)};
+our $InitAttributeInit = qr{$InitAttributePrefix(?:init\b)};
+our $InitAttribute = qr{$InitAttributeData|$InitAttributeConst|$InitAttributeInit};
# Notes to $Attribute:
# We need \b after 'init' otherwise 'initconst' will cause a false positive in a check
@@ -323,7 +326,8 @@ our $logFunctions = qr{(?x:
(?:[a-z0-9]+_){1,2}(?:printk|emerg|alert|crit|err|warning|warn|notice|info|debug|dbg|vdbg|devel|cont|WARN)(?:_ratelimited|_once|)|
WARN(?:_RATELIMIT|_ONCE|)|
panic|
- MODULE_[A-Z_]+
+ MODULE_[A-Z_]+|
+ seq_vprintf|seq_printf|seq_puts
)};
our $signature_tags = qr{(?xi:
@@ -442,8 +446,9 @@ sub seed_camelcase_file {
next if ($line !~ /(?:[A-Z][a-z]|[a-z][A-Z])/);
if ($line =~ /^[ \t]*(?:#[ \t]*define|typedef\s+$Type)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)/) {
$camelcase{$1} = 1;
- }
- elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*\(/) {
+ } elsif ($line =~ /^\s*$Declare\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[\(\[,;]/) {
+ $camelcase{$1} = 1;
+ } elsif ($line =~ /^\s*(?:union|struct|enum)\s+(\w*(?:[A-Z][a-z]|[a-z][A-Z])\w*)\s*[;\{]/) {
$camelcase{$1} = 1;
}
}
@@ -1512,6 +1517,14 @@ sub rtrim {
return $string;
}
+sub string_find_replace {
+ my ($string, $find, $replace) = @_;
+
+ $string =~ s/$find/$replace/g;
+
+ return $string;
+}
+
sub tabify {
my ($leading) = @_;
@@ -1612,6 +1625,8 @@ sub process {
my @setup_docs = ();
my $setup_docs = 0;
+ my $camelcase_file_seeded = 0;
+
sanitise_line_reset();
my $line;
foreach my $rawline (@rawlines) {
@@ -1754,11 +1769,11 @@ sub process {
# extract the filename as it passes
if ($line =~ /^diff --git.*?(\S+)$/) {
$realfile = $1;
- $realfile =~ s@^([^/]*)/@@;
+ $realfile =~ s@^([^/]*)/@@ if (!$file);
$in_commit_log = 0;
} elsif ($line =~ /^\+\+\+\s+(\S+)/) {
$realfile = $1;
- $realfile =~ s@^([^/]*)/@@;
+ $realfile =~ s@^([^/]*)/@@ if (!$file);
$in_commit_log = 0;
$p1_prefix = $1;
@@ -1947,6 +1962,18 @@ sub process {
$rpt_cleaners = 1;
}
+# Check for FSF mailing addresses.
+ if ($rawline =~ /You should have received a copy/ ||
+ $rawline =~ /write to the Free Software/ ||
+ $rawline =~ /59 Temple Place/ ||
+ $rawline =~ /51 Franklin Street/) {
+ my $herevet = "$here\n" . cat_vet($rawline) . "\n";
+ my $msg_type = \&ERROR;
+ $msg_type = \&CHK if ($file);
+ &{$msg_type}("FSF_MAILING_ADDRESS",
+ "Do not include the paragraph about writing to the Free Software Foundation's mailing address from the sample GPL notice. The FSF has changed addresses in the past, and may do so again. Linux already includes a copy of the GPL.\n" . $herevet)
+ }
+
# check for Kconfig help text having a real description
# Only applies when adding the entry originally, after that we do not have
# sufficient context to determine whether it is indeed long enough.
@@ -2838,7 +2865,7 @@ sub process {
\+=|-=|\*=|\/=|%=|\^=|\|=|&=|
=>|->|<<|>>|<|>|=|!|~|
&&|\|\||,|\^|\+\+|--|&|\||\+|-|\*|\/|%|
- \?|:
+ \?:|\?|:
}x;
my @elements = split(/($ops|;)/, $opline);
@@ -3061,15 +3088,13 @@ sub process {
$ok = 1;
}
- # Ignore ?:
- if (($opv eq ':O' && $ca =~ /\?$/) ||
- ($op eq '?' && $cc =~ /^:/)) {
- $ok = 1;
- }
-
+ # messages are ERROR, but ?: are CHK
if ($ok == 0) {
- if (ERROR("SPACING",
- "spaces required around that '$op' $at\n" . $hereptr)) {
+ my $msg_type = \&ERROR;
+ $msg_type = \&CHK if (($op eq '?:' || $op eq '?' || $op eq ':') && $ctx =~ /VxV/);
+
+ if (&{$msg_type}("SPACING",
+ "spaces required around that '$op' $at\n" . $hereptr)) {
$good = rtrim($fix_elements[$n]) . " " . trim($fix_elements[$n + 1]) . " ";
if (defined $fix_elements[$n + 2]) {
$fix_elements[$n + 2] =~ s/^\s+//;
@@ -3208,21 +3233,10 @@ sub process {
}
# Return is not a function.
- if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) {
+ if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) {
my $spacing = $1;
- my $value = $2;
-
- # Flatten any parentheses
- $value =~ s/\(/ \(/g;
- $value =~ s/\)/\) /g;
- while ($value =~ s/\[[^\[\]]*\]/1/ ||
- $value !~ /(?:$Ident|-?$Constant)\s*
- $Compare\s*
- (?:$Ident|-?$Constant)/x &&
- $value =~ s/\([^\(\)]*\)/1/) {
- }
-#print "value<$value>\n";
- if ($value =~ /^\s*(?:$Ident|-?$Constant)\s*$/) {
+ if ($^V && $^V ge 5.10.0 &&
+ $stat =~ /^.\s*return\s*$balanced_parens\s*;\s*$/) {
ERROR("RETURN_PARENTHESES",
"return is not a function, parentheses are not required\n" . $herecurr);
@@ -3231,6 +3245,7 @@ sub process {
"space required before the open parenthesis '('\n" . $herecurr);
}
}
+
# Return of what appears to be an errno should normally be -'ve
if ($line =~ /^.\s*return\s*(E[A-Z]*)\s*;/) {
my $name = $1;
@@ -3396,7 +3411,13 @@ sub process {
while ($var =~ m{($Ident)}g) {
my $word = $1;
next if ($word !~ /[A-Z][a-z]|[a-z][A-Z]/);
- seed_camelcase_includes() if ($check);
+ if ($check) {
+ seed_camelcase_includes();
+ if (!$file && !$camelcase_file_seeded) {
+ seed_camelcase_file($realfile);
+ $camelcase_file_seeded = 1;
+ }
+ }
if (!defined $camelcase{$word}) {
$camelcase{$word} = 1;
CHK("CAMELCASE",
@@ -3725,14 +3746,6 @@ sub process {
}
}
-sub string_find_replace {
- my ($string, $find, $replace) = @_;
-
- $string =~ s/$find/$replace/g;
-
- return $string;
-}
-
# check for bad placement of section $InitAttribute (e.g.: __initdata)
if ($line =~ /(\b$InitAttribute\b)/) {
my $attr = $1;
@@ -3751,6 +3764,35 @@ sub string_find_replace {
}
}
+# check for $InitAttributeData (ie: __initdata) with const
+ if ($line =~ /\bconst\b/ && $line =~ /($InitAttributeData)/) {
+ my $attr = $1;
+ $attr =~ /($InitAttributePrefix)(.*)/;
+ my $attr_prefix = $1;
+ my $attr_type = $2;
+ if (ERROR("INIT_ATTRIBUTE",
+ "Use of const init definition must use ${attr_prefix}initconst\n" . $herecurr) &&
+ $fix) {
+ $fixed[$linenr - 1] =~
+ s/$InitAttributeData/${attr_prefix}initconst/;
+ }
+ }
+
+# check for $InitAttributeConst (ie: __initconst) without const
+ if ($line !~ /\bconst\b/ && $line =~ /($InitAttributeConst)/) {
+ my $attr = $1;
+ if (ERROR("INIT_ATTRIBUTE",
+ "Use of $attr requires a separate use of const\n" . $herecurr) &&
+ $fix) {
+ my $lead = $fixed[$linenr - 1] =~
+ /(^\+\s*(?:static\s+))/;
+ $lead = rtrim($1);
+ $lead = "$lead " if ($lead !~ /^\+$/);
+ $lead = "${lead}const ";
+ $fixed[$linenr - 1] =~ s/(^\+\s*(?:static\s+))/$lead/;
+ }
+ }
+
# prefer usleep_range over udelay
if ($line =~ /\budelay\s*\(\s*(\d+)\s*\)/) {
# ignore udelay's < 10, however
@@ -3810,8 +3852,8 @@ sub string_find_replace {
# check for memory barriers without a comment.
if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) {
if (!ctx_has_comment($first_line, $linenr)) {
- CHK("MEMORY_BARRIER",
- "memory barrier without comment\n" . $herecurr);
+ WARN("MEMORY_BARRIER",
+ "memory barrier without comment\n" . $herecurr);
}
}
# check of hardware specific defines
@@ -3835,7 +3877,8 @@ sub string_find_replace {
}
# Check for __inline__ and __inline, prefer inline
- if ($line =~ /\b(__inline__|__inline)\b/) {
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b(__inline__|__inline)\b/) {
if (WARN("INLINE",
"plain inline is preferred over $1\n" . $herecurr) &&
$fix) {
@@ -3845,19 +3888,22 @@ sub string_find_replace {
}
# Check for __attribute__ packed, prefer __packed
- if ($line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*\bpacked\b/) {
WARN("PREFER_PACKED",
"__packed is preferred over __attribute__((packed))\n" . $herecurr);
}
# Check for __attribute__ aligned, prefer __aligned
- if ($line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(.*aligned/) {
WARN("PREFER_ALIGNED",
"__aligned(size) is preferred over __attribute__((aligned(size)))\n" . $herecurr);
}
# Check for __attribute__ format(printf, prefer __printf
- if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*printf/) {
if (WARN("PREFER_PRINTF",
"__printf(string-index, first-to-check) is preferred over __attribute__((format(printf, string-index, first-to-check)))\n" . $herecurr) &&
$fix) {
@@ -3867,7 +3913,8 @@ sub string_find_replace {
}
# Check for __attribute__ format(scanf, prefer __scanf
- if ($line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
+ if ($realfile !~ m@\binclude/uapi/@ &&
+ $line =~ /\b__attribute__\s*\(\s*\(\s*format\s*\(\s*scanf\b/) {
if (WARN("PREFER_SCANF",
"__scanf(string-index, first-to-check) is preferred over __attribute__((format(scanf, string-index, first-to-check)))\n" . $herecurr) &&
$fix) {
@@ -3903,9 +3950,9 @@ sub string_find_replace {
}
# check for seq_printf uses that could be seq_puts
- if ($line =~ /\bseq_printf\s*\(/) {
+ if ($sline =~ /\bseq_printf\s*\(.*"\s*\)\s*;\s*$/) {
my $fmt = get_quoted_string($line, $rawline);
- if ($fmt !~ /[^\\]\%/) {
+ if ($fmt ne "" && $fmt !~ /[^\\]\%/) {
if (WARN("PREFER_SEQ_PUTS",
"Prefer seq_puts to seq_printf\n" . $herecurr) &&
$fix) {
@@ -3972,6 +4019,23 @@ sub string_find_replace {
}
}
+# check for naked sscanf
+ if ($^V && $^V ge 5.10.0 &&
+ defined $stat &&
+ $stat =~ /\bsscanf\b/ &&
+ ($stat !~ /$Ident\s*=\s*sscanf\s*$balanced_parens/ &&
+ $stat !~ /\bsscanf\s*$balanced_parens\s*(?:$Compare)/ &&
+ $stat !~ /(?:$Compare)\s*\bsscanf\s*$balanced_parens/)) {
+ my $lc = $stat =~ tr@\n@@;
+ $lc = $lc + $linenr;
+ my $stat_real = raw_line($linenr, 0);
+ for (my $count = $linenr + 1; $count <= $lc; $count++) {
+ $stat_real = $stat_real . "\n" . raw_line($count, 0);
+ }
+ WARN("NAKED_SSCANF",
+ "unchecked sscanf return value\n" . "$here\n$stat_real\n");
+ }
+
# check for new externs in .h files.
if ($realfile =~ /\.h$/ &&
$line =~ /^\+\s*(extern\s+)$Type\s*$Ident\s*\(/s) {
@@ -4190,6 +4254,12 @@ sub string_find_replace {
"usage of NR_CPUS is often wrong - consider using cpu_possible(), num_possible_cpus(), for_each_possible_cpu(), etc\n" . $herecurr);
}
+# Use of __ARCH_HAS_<FOO> or ARCH_HAVE_<BAR> is wrong.
+ if ($line =~ /\+\s*#\s*define\s+((?:__)?ARCH_(?:HAS|HAVE)\w*)\b/) {
+ ERROR("DEFINE_ARCH_HAS",
+ "#define of '$1' is wrong - use Kconfig variables or standard guards instead\n" . $herecurr);
+ }
+
# check for %L{u,d,i} in strings
my $string;
while ($line =~ /(?:^|")([X\t]*)(?:"|$)/g) {
diff --git a/scripts/docproc.c b/scripts/docproc.c
index 4cfdc17..2b69eaf 100644
--- a/scripts/docproc.c
+++ b/scripts/docproc.c
@@ -72,6 +72,7 @@ FILELINE * docsection;
#define FUNCTION "-function"
#define NOFUNCTION "-nofunction"
#define NODOCSECTIONS "-no-doc-sections"
+#define SHOWNOTFOUND "-show-not-found"
static char *srctree, *kernsrctree;
@@ -294,6 +295,7 @@ static void singfunc(char * filename, char * line)
int startofsym = 1;
vec[idx++] = KERNELDOC;
vec[idx++] = DOCBOOK;
+ vec[idx++] = SHOWNOTFOUND;
/* Split line up in individual parameters preceded by FUNCTION */
for (i=0; line[i]; i++) {
@@ -325,7 +327,8 @@ static void singfunc(char * filename, char * line)
*/
static void docsect(char *filename, char *line)
{
- char *vec[6]; /* kerneldoc -docbook -function "section" file NULL */
+ /* kerneldoc -docbook -show-not-found -function "section" file NULL */
+ char *vec[7];
char *s;
for (s = line; *s; s++)
@@ -341,10 +344,11 @@ static void docsect(char *filename, char *line)
vec[0] = KERNELDOC;
vec[1] = DOCBOOK;
- vec[2] = FUNCTION;
- vec[3] = line;
- vec[4] = filename;
- vec[5] = NULL;
+ vec[2] = SHOWNOTFOUND;
+ vec[3] = FUNCTION;
+ vec[4] = line;
+ vec[5] = filename;
+ vec[6] = NULL;
exec_kernel_doc(vec);
}
diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
index b482f16..ef47409 100644
--- a/scripts/gen_initramfs_list.sh
+++ b/scripts/gen_initramfs_list.sh
@@ -240,12 +240,24 @@ case "$arg" in
output_file="$1"
cpio_list="$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)"
output=${cpio_list}
- echo "$output_file" | grep -q "\.gz$" && compr="gzip -n -9 -f"
- echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
- echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
- echo "$output_file" | grep -q "\.xz$" && \
- compr="xz --check=crc32 --lzma2=dict=1MiB"
- echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
+ echo "$output_file" | grep -q "\.gz$" \
+ && [ -x "`which gzip 2> /dev/null`" ] \
+ && compr="gzip -n -9 -f"
+ echo "$output_file" | grep -q "\.bz2$" \
+ && [ -x "`which bzip2 2> /dev/null`" ] \
+ && compr="bzip2 -9 -f"
+ echo "$output_file" | grep -q "\.lzma$" \
+ && [ -x "`which lzma 2> /dev/null`" ] \
+ && compr="lzma -9 -f"
+ echo "$output_file" | grep -q "\.xz$" \
+ && [ -x "`which xz 2> /dev/null`" ] \
+ && compr="xz --check=crc32 --lzma2=dict=1MiB"
+ echo "$output_file" | grep -q "\.lzo$" \
+ && [ -x "`which lzop 2> /dev/null`" ] \
+ && compr="lzop -9 -f"
+ echo "$output_file" | grep -q "\.lz4$" \
+ && [ -x "`which lz4 2> /dev/null`" ] \
+ && compr="lz4 -9 -f"
echo "$output_file" | grep -q "\.cpio$" && compr="cat"
shift
;;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index 4305b2f..dbd3e1e 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -257,6 +257,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June',
'July', 'August', 'September', 'October',
'November', 'December')[(localtime)[4]] .
" " . ((localtime)[5]+1900);
+my $show_not_found = 0;
# Essentially these are globals.
# They probably want to be tidied up, made more localised or something.
@@ -369,6 +370,8 @@ while ($ARGV[0] =~ m/^-(.*)/) {
usage();
} elsif ($cmd eq '-no-doc-sections') {
$no_doc_sections = 1;
+ } elsif ($cmd eq '-show-not-found') {
+ $show_not_found = 1;
}
}
@@ -2536,6 +2539,9 @@ sub process_file($) {
}
if ($initial_section_counter == $section_counter) {
print STDERR "Warning(${file}): no structured comments found\n";
+ if (($function_only == 1) && ($show_not_found == 1)) {
+ print STDERR " Was looking for '$_'.\n" for keys %function_table;
+ }
if ($output_mode eq "xml") {
# The template wants at least one RefEntry here; make one.
print "<refentry>\n";
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 8247979..bfcea5d 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -599,18 +599,17 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
else
export = export_from_sec(info, get_secindex(info, sym));
+ /* CRC'd symbol */
+ if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
+ crc = (unsigned int) sym->st_value;
+ sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
+ export);
+ }
+
switch (sym->st_shndx) {
case SHN_COMMON:
warn("\"%s\" [%s] is COMMON symbol\n", symname, mod->name);
break;
- case SHN_ABS:
- /* CRC'd symbol */
- if (strncmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
- crc = (unsigned int) sym->st_value;
- sym_update_crc(symname + strlen(CRC_PFX), mod, crc,
- export);
- }
- break;
case SHN_UNDEF:
/* undefined symbol */
if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL &&
diff --git a/scripts/sortextable.c b/scripts/sortextable.c
index 7c2310c..5f7a8b6 100644
--- a/scripts/sortextable.c
+++ b/scripts/sortextable.c
@@ -152,6 +152,30 @@ static void (*w2)(uint16_t, uint16_t *);
typedef void (*table_sort_t)(char *, int);
+/*
+ * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of
+ * the way to -256..-1, to avoid conflicting with real section
+ * indices.
+ */
+#define SPECIAL(i) ((i) - (SHN_HIRESERVE + 1))
+
+static inline int is_shndx_special(unsigned int i)
+{
+ return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE;
+}
+
+/* Accessor for sym->st_shndx, hides ugliness of "64k sections" */
+static inline unsigned int get_secindex(unsigned int shndx,
+ unsigned int sym_offs,
+ const Elf32_Word *symtab_shndx_start)
+{
+ if (is_shndx_special(shndx))
+ return SPECIAL(shndx);
+ if (shndx != SHN_XINDEX)
+ return shndx;
+ return r(&symtab_shndx_start[sym_offs]);
+}
+
/* 32 bit and 64 bit are very similar */
#include "sortextable.h"
#define SORTEXTABLE_64
diff --git a/scripts/sortextable.h b/scripts/sortextable.h
index f5eb43d..8fac3fd 100644
--- a/scripts/sortextable.h
+++ b/scripts/sortextable.h
@@ -98,6 +98,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
Elf_Shdr *symtab_sec = NULL;
Elf_Shdr *extab_sec = NULL;
Elf_Sym *sym;
+ const Elf_Sym *symtab;
+ Elf32_Word *symtab_shndx_start = NULL;
Elf_Sym *sort_needed_sym;
Elf_Shdr *sort_needed_sec;
Elf_Rel *relocs = NULL;
@@ -109,11 +111,22 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
int extab_index = 0;
int i;
int idx;
+ unsigned int num_sections;
+ unsigned int secindex_strings;
shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff));
- shstrtab_sec = shdr + r2(&ehdr->e_shstrndx);
+
+ num_sections = r2(&ehdr->e_shnum);
+ if (num_sections == SHN_UNDEF)
+ num_sections = _r(&shdr[0].sh_size);
+
+ secindex_strings = r2(&ehdr->e_shstrndx);
+ if (secindex_strings == SHN_XINDEX)
+ secindex_strings = r(&shdr[0].sh_link);
+
+ shstrtab_sec = shdr + secindex_strings;
secstrtab = (const char *)ehdr + _r(&shstrtab_sec->sh_offset);
- for (i = 0; i < r2(&ehdr->e_shnum); i++) {
+ for (i = 0; i < num_sections; i++) {
idx = r(&shdr[i].sh_name);
if (strcmp(secstrtab + idx, "__ex_table") == 0) {
extab_sec = shdr + i;
@@ -129,6 +142,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
symtab_sec = shdr + i;
if (strcmp(secstrtab + idx, ".strtab") == 0)
strtab_sec = shdr + i;
+ if (r(&shdr[i].sh_type) == SHT_SYMTAB_SHNDX)
+ symtab_shndx_start = (Elf32_Word *)(
+ (const char *)ehdr + _r(&shdr[i].sh_offset));
}
if (strtab_sec == NULL) {
fprintf(stderr, "no .strtab in file: %s\n", fname);
@@ -138,6 +154,8 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
fprintf(stderr, "no .symtab in file: %s\n", fname);
fail_file();
}
+ symtab = (const Elf_Sym *)((const char *)ehdr +
+ _r(&symtab_sec->sh_offset));
if (extab_sec == NULL) {
fprintf(stderr, "no __ex_table in file: %s\n", fname);
fail_file();
@@ -176,7 +194,9 @@ do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort)
fname);
fail_file();
}
- sort_needed_sec = &shdr[r2(&sort_needed_sym->st_shndx)];
+ sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx),
+ sort_needed_sym - symtab,
+ symtab_shndx_start)];
sort_done_location = (void *)ehdr +
_r(&sort_needed_sec->sh_offset) +
_r(&sort_needed_sym->st_value) -