diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 15:45:43 +0900 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-11-13 15:45:43 +0900 |
commit | 5cbb3d216e2041700231bcfc383ee5f8b7fc8b74 (patch) | |
tree | a738fa82dbcefa9bd283c08bc67f38827be63937 /scripts | |
parent | 9bc9ccd7db1c9f043f75380b5a5b94912046a60e (diff) | |
parent | 4e9b45a19241354daec281d7a785739829b52359 (diff) |
Merge branch 'akpm' (patches from Andrew Morton)
Merge first patch-bomb from Andrew Morton:
"Quite a lot of other stuff is banked up awaiting further
next->mainline merging, but this batch contains:
- Lots of random misc patches
- OCFS2
- Most of MM
- backlight updates
- lib/ updates
- printk updates
- checkpatch updates
- epoll tweaking
- rtc updates
- hfs
- hfsplus
- documentation
- procfs
- update gcov to gcc-4.7 format
- IPC"
* emailed patches from Andrew Morton <akpm@linux-foundation.org>: (269 commits)
ipc, msg: fix message length check for negative values
ipc/util.c: remove unnecessary work pending test
devpts: plug the memory leak in kill_sb
./Makefile: export initial ramdisk compression config option
init/Kconfig: add option to disable kernel compression
drivers: w1: make w1_slave::flags long to avoid memory corruption
drivers/w1/masters/ds1wm.cuse dev_get_platdata()
drivers/memstick/core/ms_block.c: fix unreachable state in h_msb_read_page()
drivers/memstick/core/mspro_block.c: fix attributes array allocation
drivers/pps/clients/pps-gpio.c: remove redundant of_match_ptr
kernel/panic.c: reduce 1 byte usage for print tainted buffer
gcov: reuse kbasename helper
kernel/gcov/fs.c: use pr_warn()
kernel/module.c: use pr_foo()
gcov: compile specific gcov implementation based on gcc version
gcov: add support for gcc 4.7 gcov format
gcov: move gcov structs definitions to a gcc version specific file
kernel/taskstats.c: return -ENOMEM when alloc memory fails in add_del_listener()
kernel/taskstats.c: add nla_nest_cancel() for failure processing between nla_nest_start() and nla_nest_end()
kernel/sysctl_binary.c: use scnprintf() instead of snprintf()
...
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/checkpatch.pl | 166 | ||||
-rw-r--r-- | scripts/docproc.c | 14 | ||||
-rw-r--r-- | scripts/gen_initramfs_list.sh | 24 | ||||
-rwxr-xr-x | scripts/kernel-doc | 6 | ||||
-rw-r--r-- | scripts/mod/modpost.c | 15 | ||||
-rw-r--r-- | scripts/sortextable.c | 24 | ||||
-rw-r--r-- | scripts/sortextable.h | 26 |
7 files changed, 205 insertions, 70 deletions
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 66cad506b8a..61090e0ff61 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 4cfdc1797eb..2b69eaf5b64 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 b482f162a18..ef474098d9f 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 4305b2f2ec5..dbd3e1ebbda 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 8247979e8f6..bfcea5d3b27 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 7c2310c5b99..5f7a8b663cb 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 f5eb43d4292..8fac3fd697a 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) - |