diff options
Diffstat (limited to 'scripts')
27 files changed, 643 insertions, 717 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore index 4aa1806c59c2..ef45f96cd7a5 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -2,11 +2,10 @@ # Generated files # bin2c -conmakehash kallsyms unifdef recordmcount -sortextable +sorttable asn1_compiler extract-cert sign-file diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include index bfb44b265a94..85334dc8c997 100644 --- a/scripts/Kconfig.include +++ b/scripts/Kconfig.include @@ -31,6 +31,10 @@ cc-option = $(success,$(CC) -Werror $(CLANG_FLAGS) $(1) -S -x c /dev/null -o /de # Return y if the linker supports <flag>, n otherwise ld-option = $(success,$(LD) -v $(1)) +# $(as-instr,<instr>) +# Return y if the assembler supports <instr>, n otherwise +as-instr = $(success,printf "%b\n" "$(1)" | $(CC) $(CLANG_FLAGS) -c -x assembler -o /dev/null -) + # check if $(CC) and $(LD) exist $(error-if,$(failure,command -v $(CC)),compiler '$(CC)' not found) $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found) diff --git a/scripts/Makefile b/scripts/Makefile index 00c47901cb06..4d41f48e7376 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -4,26 +4,32 @@ # the kernel for the build process. # --------------------------------------------------------------------------- # kallsyms: Find all symbols in vmlinux -# conmakehash: Create chartable -# conmakehash: Create arrays for initializing the kernel console tables HOST_EXTRACFLAGS += -I$(srctree)/tools/include hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c hostprogs-$(CONFIG_KALLSYMS) += kallsyms -hostprogs-$(CONFIG_VT) += conmakehash hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount -hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable +hostprogs-$(CONFIG_BUILDTIME_TABLE_SORT) += sorttable hostprogs-$(CONFIG_ASN1) += asn1_compiler hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert -HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include +HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include HOSTLDLIBS_sign-file = -lcrypto HOSTLDLIBS_extract-cert = -lcrypto +ifdef CONFIG_UNWINDER_ORC +ifeq ($(ARCH),x86_64) +ARCH := x86 +endif +HOSTCFLAGS_sorttable.o += -I$(srctree)/tools/arch/x86/include +HOSTCFLAGS_sorttable.o += -DUNWINDER_ORC_ENABLED +HOSTLDLIBS_sorttable = -lpthread +endif + always := $(hostprogs-y) $(hostprogs-m) # The following hostprogs-y programs are only build on demand diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 7548569e8076..90baf7d70911 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -158,8 +158,6 @@ class HeaderParser(object): break self.reader.close() - print('Parsed description of %d helper function(s)' % len(self.helpers), - file=sys.stderr) ############################################################################### diff --git a/scripts/coccinelle/free/devm_free.cocci b/scripts/coccinelle/free/devm_free.cocci index 441799b5359b..9330d4294b74 100644 --- a/scripts/coccinelle/free/devm_free.cocci +++ b/scripts/coccinelle/free/devm_free.cocci @@ -52,8 +52,6 @@ expression x; | x = devm_ioremap(...) | - x = devm_ioremap_nocache(...) -| x = devm_ioport_map(...) ) @@ -85,8 +83,6 @@ position p; | x = ioremap(...) | - x = ioremap_nocache(...) -| x = ioport_map(...) ) ... diff --git a/scripts/coccinelle/free/iounmap.cocci b/scripts/coccinelle/free/iounmap.cocci index 0e60e1113a1d..63b81d0c97b6 100644 --- a/scripts/coccinelle/free/iounmap.cocci +++ b/scripts/coccinelle/free/iounmap.cocci @@ -23,7 +23,7 @@ int ret; position p1,p2,p3; @@ -e = \(ioremap@p1\|ioremap_nocache@p1\)(...) +e = \(ioremap@p1\)(...) ... when != iounmap(e) if (<+...e...+>) S ... when any diff --git a/scripts/conmakehash.c b/scripts/conmakehash.c deleted file mode 100644 index cddd789fe46e..000000000000 --- a/scripts/conmakehash.c +++ /dev/null @@ -1,290 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * conmakehash.c - * - * Create arrays for initializing the kernel folded tables (using a hash - * table turned out to be to limiting...) Unfortunately we can't simply - * preinitialize the tables at compile time since kfree() cannot accept - * memory not allocated by kmalloc(), and doing our own memory management - * just for this seems like massive overkill. - * - * Copyright (C) 1995-1997 H. Peter Anvin - */ - -#include <stdio.h> -#include <stdlib.h> -#include <sysexits.h> -#include <string.h> -#include <ctype.h> - -#define MAX_FONTLEN 256 - -typedef unsigned short unicode; - -static void usage(char *argv0) -{ - fprintf(stderr, "Usage: \n" - " %s chartable [hashsize] [hashstep] [maxhashlevel]\n", argv0); - exit(EX_USAGE); -} - -static int getunicode(char **p0) -{ - char *p = *p0; - - while (*p == ' ' || *p == '\t') - p++; - if (*p != 'U' || p[1] != '+' || - !isxdigit(p[2]) || !isxdigit(p[3]) || !isxdigit(p[4]) || - !isxdigit(p[5]) || isxdigit(p[6])) - return -1; - *p0 = p+6; - return strtol(p+2,0,16); -} - -unicode unitable[MAX_FONTLEN][255]; - /* Massive overkill, but who cares? */ -int unicount[MAX_FONTLEN]; - -static void addpair(int fp, int un) -{ - int i; - - if ( un <= 0xfffe ) - { - /* Check it isn't a duplicate */ - - for ( i = 0 ; i < unicount[fp] ; i++ ) - if ( unitable[fp][i] == un ) - return; - - /* Add to list */ - - if ( unicount[fp] > 254 ) - { - fprintf(stderr, "ERROR: Only 255 unicodes/glyph permitted!\n"); - exit(EX_DATAERR); - } - - unitable[fp][unicount[fp]] = un; - unicount[fp]++; - } - - /* otherwise: ignore */ -} - -int main(int argc, char *argv[]) -{ - FILE *ctbl; - char *tblname; - char buffer[65536]; - int fontlen; - int i, nuni, nent; - int fp0, fp1, un0, un1; - char *p, *p1; - - if ( argc < 2 || argc > 5 ) - usage(argv[0]); - - if ( !strcmp(argv[1],"-") ) - { - ctbl = stdin; - tblname = "stdin"; - } - else - { - ctbl = fopen(tblname = argv[1], "r"); - if ( !ctbl ) - { - perror(tblname); - exit(EX_NOINPUT); - } - } - - /* For now we assume the default font is always 256 characters. */ - fontlen = 256; - - /* Initialize table */ - - for ( i = 0 ; i < fontlen ; i++ ) - unicount[i] = 0; - - /* Now we come to the tricky part. Parse the input table. */ - - while ( fgets(buffer, sizeof(buffer), ctbl) != NULL ) - { - if ( (p = strchr(buffer, '\n')) != NULL ) - *p = '\0'; - else - fprintf(stderr, "%s: Warning: line too long\n", tblname); - - p = buffer; - -/* - * Syntax accepted: - * <fontpos> <unicode> <unicode> ... - * <range> idem - * <range> <unicode range> - * - * where <range> ::= <fontpos>-<fontpos> - * and <unicode> ::= U+<h><h><h><h> - * and <h> ::= <hexadecimal digit> - */ - - while (*p == ' ' || *p == '\t') - p++; - if (!*p || *p == '#') - continue; /* skip comment or blank line */ - - fp0 = strtol(p, &p1, 0); - if (p1 == p) - { - fprintf(stderr, "Bad input line: %s\n", buffer); - exit(EX_DATAERR); - } - p = p1; - - while (*p == ' ' || *p == '\t') - p++; - if (*p == '-') - { - p++; - fp1 = strtol(p, &p1, 0); - if (p1 == p) - { - fprintf(stderr, "Bad input line: %s\n", buffer); - exit(EX_DATAERR); - } - p = p1; - } - else - fp1 = 0; - - if ( fp0 < 0 || fp0 >= fontlen ) - { - fprintf(stderr, - "%s: Glyph number (0x%x) larger than font length\n", - tblname, fp0); - exit(EX_DATAERR); - } - if ( fp1 && (fp1 < fp0 || fp1 >= fontlen) ) - { - fprintf(stderr, - "%s: Bad end of range (0x%x)\n", - tblname, fp1); - exit(EX_DATAERR); - } - - if (fp1) - { - /* we have a range; expect the word "idem" or a Unicode range of the - same length */ - while (*p == ' ' || *p == '\t') - p++; - if (!strncmp(p, "idem", 4)) - { - for (i=fp0; i<=fp1; i++) - addpair(i,i); - p += 4; - } - else - { - un0 = getunicode(&p); - while (*p == ' ' || *p == '\t') - p++; - if (*p != '-') - { - fprintf(stderr, -"%s: Corresponding to a range of font positions, there should be a Unicode range\n", - tblname); - exit(EX_DATAERR); - } - p++; - un1 = getunicode(&p); - if (un0 < 0 || un1 < 0) - { - fprintf(stderr, -"%s: Bad Unicode range corresponding to font position range 0x%x-0x%x\n", - tblname, fp0, fp1); - exit(EX_DATAERR); - } - if (un1 - un0 != fp1 - fp0) - { - fprintf(stderr, -"%s: Unicode range U+%x-U+%x not of the same length as font position range 0x%x-0x%x\n", - tblname, un0, un1, fp0, fp1); - exit(EX_DATAERR); - } - for(i=fp0; i<=fp1; i++) - addpair(i,un0-fp0+i); - } - } - else - { - /* no range; expect a list of unicode values for a single font position */ - - while ( (un0 = getunicode(&p)) >= 0 ) - addpair(fp0, un0); - } - while (*p == ' ' || *p == '\t') - p++; - if (*p && *p != '#') - fprintf(stderr, "%s: trailing junk (%s) ignored\n", tblname, p); - } - - /* Okay, we hit EOF, now output hash table */ - - fclose(ctbl); - - - /* Compute total size of Unicode list */ - nuni = 0; - for ( i = 0 ; i < fontlen ; i++ ) - nuni += unicount[i]; - - printf("\ -/*\n\ - * Do not edit this file; it was automatically generated by\n\ - *\n\ - * conmakehash %s > [this file]\n\ - *\n\ - */\n\ -\n\ -#include <linux/types.h>\n\ -\n\ -u8 dfont_unicount[%d] = \n\ -{\n\t", argv[1], fontlen); - - for ( i = 0 ; i < fontlen ; i++ ) - { - printf("%3d", unicount[i]); - if ( i == fontlen-1 ) - printf("\n};\n"); - else if ( i % 8 == 7 ) - printf(",\n\t"); - else - printf(", "); - } - - printf("\nu16 dfont_unitable[%d] = \n{\n\t", nuni); - - fp0 = 0; - nent = 0; - for ( i = 0 ; i < nuni ; i++ ) - { - while ( nent >= unicount[fp0] ) - { - fp0++; - nent = 0; - } - printf("0x%04x", unitable[fp0][nent++]); - if ( i == nuni-1 ) - printf("\n};\n"); - else if ( i % 8 == 7 ) - printf(",\n\t"); - else - printf(", "); - } - - exit(EX_OK); -} diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index d7986ee18012..756f0fa9203f 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -691,6 +691,11 @@ static void check_alias_paths(struct check *c, struct dt_info *dti, return; for_each_property(node, prop) { + if (streq(prop->name, "phandle") + || streq(prop->name, "linux,phandle")) { + continue; + } + if (!prop->val.val || !get_node_by_path(dti->dt, prop->val.val)) { FAIL_PROP(c, dti, node, prop, "aliases property is not a valid node (%s)", prop->val.val); diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 2ed4dc1f07fd..40dcf4f149da 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -2,6 +2,8 @@ /* * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005. */ +%locations + %{ #include <stdio.h> #include <inttypes.h> @@ -17,6 +19,8 @@ extern void yyerror(char const *s); treesource_error = true; \ } while (0) +#define YYERROR_CALL(msg) yyerror(msg) + extern struct dt_info *parser_output; extern bool treesource_error; %} diff --git a/scripts/dtc/fstree.c b/scripts/dtc/fstree.c index 9871689b4afb..5e59594ab301 100644 --- a/scripts/dtc/fstree.c +++ b/scripts/dtc/fstree.c @@ -30,7 +30,7 @@ static struct node *read_fstree(const char *dirname) tmpname = join_path(dirname, de->d_name); - if (lstat(tmpname, &st) < 0) + if (stat(tmpname, &st) < 0) die("stat(%s): %s\n", tmpname, strerror(errno)); if (S_ISREG(st.st_mode)) { diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index 179168ec63e9..d6ce7c052dc8 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -15,8 +15,10 @@ * that the given buffer contains what appears to be a flattened * device tree with sane information in its header. */ -int fdt_ro_probe_(const void *fdt) +int32_t fdt_ro_probe_(const void *fdt) { + uint32_t totalsize = fdt_totalsize(fdt); + if (fdt_magic(fdt) == FDT_MAGIC) { /* Complete tree */ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) @@ -31,7 +33,10 @@ int fdt_ro_probe_(const void *fdt) return -FDT_ERR_BADMAGIC; } - return 0; + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; } static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) diff --git a/scripts/dtc/libfdt/fdt_addresses.c b/scripts/dtc/libfdt/fdt_addresses.c index d8ba8ec60c6c..9a82cd0ba2f9 100644 --- a/scripts/dtc/libfdt/fdt_addresses.c +++ b/scripts/dtc/libfdt/fdt_addresses.c @@ -14,7 +14,7 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) { const fdt32_t *c; - int val; + uint32_t val; int len; c = fdt_getprop(fdt, nodeoffset, name, &len); @@ -25,10 +25,10 @@ static int fdt_cells(const void *fdt, int nodeoffset, const char *name) return -FDT_ERR_BADNCELLS; val = fdt32_to_cpu(*c); - if ((val <= 0) || (val > FDT_MAX_NCELLS)) + if (val > FDT_MAX_NCELLS) return -FDT_ERR_BADNCELLS; - return val; + return (int)val; } int fdt_address_cells(const void *fdt, int nodeoffset) @@ -36,6 +36,8 @@ int fdt_address_cells(const void *fdt, int nodeoffset) int val; val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; if (val == -FDT_ERR_NOTFOUND) return 2; return val; diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index e97f12b1a780..b310e49a698e 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -733,26 +733,36 @@ static int overlay_symbol_update(void *fdt, void *fdto) /* keep end marker to avoid strlen() */ e = path + path_len; - /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ - if (*path != '/') return -FDT_ERR_BADVALUE; /* get fragment name first */ s = strchr(path + 1, '/'); - if (!s) - return -FDT_ERR_BADOVERLAY; + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } frag_name = path + 1; frag_name_len = s - path - 1; /* verify format; safe since "s" lies in \0 terminated prop */ len = sizeof("/__overlay__/") - 1; - if ((e - s) < len || memcmp(s, "/__overlay__/", len)) - return -FDT_ERR_BADOVERLAY; - - rel_path = s + len; - rel_path_len = e - rel_path; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* /<fragment-name>/__overlay__/<relative-subnode-path> */ + rel_path = s + len; + rel_path_len = e - rel_path - 1; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* /<fragment-name>/__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } /* find the fragment index in which the symbol lies */ ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index 6fd9ec170dbe..a5c2797cde65 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -33,19 +33,20 @@ static int fdt_nodename_eq_(const void *fdt, int offset, const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) { + int32_t totalsize = fdt_ro_probe_(fdt); uint32_t absoffset = stroffset + fdt_off_dt_strings(fdt); size_t len; int err; const char *s, *n; - err = fdt_ro_probe_(fdt); - if (err != 0) + err = totalsize; + if (totalsize < 0) goto fail; err = -FDT_ERR_BADOFFSET; - if (absoffset >= fdt_totalsize(fdt)) + if (absoffset >= totalsize) goto fail; - len = fdt_totalsize(fdt) - absoffset; + len = totalsize - absoffset; if (fdt_magic(fdt) == FDT_MAGIC) { if (stroffset < 0) @@ -288,7 +289,7 @@ const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) const char *nameptr; int err; - if (((err = fdt_ro_probe_(fdt)) != 0) + if (((err = fdt_ro_probe_(fdt)) < 0) || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) goto fail; diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt/libfdt.h index 7b5ffd13a887..8907b09b86cc 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt/libfdt.h @@ -136,7 +136,7 @@ static inline uint32_t fdt32_ld(const fdt32_t *p) static inline void fdt32_st(void *property, uint32_t value) { - uint8_t *bp = property; + uint8_t *bp = (uint8_t *)property; bp[0] = value >> 24; bp[1] = (value >> 16) & 0xff; @@ -160,7 +160,7 @@ static inline uint64_t fdt64_ld(const fdt64_t *p) static inline void fdt64_st(void *property, uint64_t value) { - uint8_t *bp = property; + uint8_t *bp = (uint8_t *)property; bp[0] = value >> 56; bp[1] = (value >> 48) & 0xff; diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt/libfdt_internal.h index 7830e550c37a..058c7358d441 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt/libfdt_internal.h @@ -10,12 +10,12 @@ #define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) -int fdt_ro_probe_(const void *fdt); -#define FDT_RO_PROBE(fdt) \ - { \ - int err_; \ - if ((err_ = fdt_ro_probe_(fdt)) != 0) \ - return err_; \ +int32_t fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ + { \ + int32_t totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ } int fdt_check_node_offset_(const void *fdt, int offset); diff --git a/scripts/dtc/livetree.c b/scripts/dtc/livetree.c index 0c039993953a..032df5878ccc 100644 --- a/scripts/dtc/livetree.c +++ b/scripts/dtc/livetree.c @@ -526,8 +526,7 @@ struct node *get_node_by_path(struct node *tree, const char *path) p = strchr(path, '/'); for_each_child(tree, child) { - if (p && (strlen(child->name) == p-path) && - strprefixeq(path, p - path, child->name)) + if (p && strprefixeq(path, p - path, child->name)) return get_node_by_path(child, p+1); else if (!p && streq(path, child->name)) return child; diff --git a/scripts/dtc/util.c b/scripts/dtc/util.c index 48af961dcc8c..40274fb79236 100644 --- a/scripts/dtc/util.c +++ b/scripts/dtc/util.c @@ -13,6 +13,7 @@ #include <stdarg.h> #include <string.h> #include <assert.h> +#include <inttypes.h> #include <errno.h> #include <fcntl.h> @@ -393,7 +394,7 @@ void utilfdt_print_data(const char *data, int len) printf(" = <"); for (i = 0, len /= 4; i < len; i++) - printf("0x%08x%s", fdt32_to_cpu(cell[i]), + printf("0x%08" PRIx32 "%s", fdt32_to_cpu(cell[i]), i < (len - 1) ? " " : ""); printf(">"); } else { diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index ca5cb52928e3..5a4172dd0f84 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -12,7 +12,11 @@ */ #ifdef __GNUC__ +#ifdef __clang__ #define PRINTF(i, j) __attribute__((format (printf, i, j))) +#else +#define PRINTF(i, j) __attribute__((format (gnu_printf, i, j))) +#endif #define NORETURN __attribute__((noreturn)) #else #define PRINTF(i, j) diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index f2761e24cf40..6dba95d23207 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.5.0-g702c1b6c" +#define DTC_VERSION "DTC 1.5.0-gc40aeb60" diff --git a/scripts/find-unused-docs.sh b/scripts/find-unused-docs.sh index 3f46f8977dc4..ee6a50e33aba 100755 --- a/scripts/find-unused-docs.sh +++ b/scripts/find-unused-docs.sh @@ -54,7 +54,7 @@ for file in `find $1 -name '*.c'`; do if [[ ${FILES_INCLUDED[$file]+_} ]]; then continue; fi - str=$(scripts/kernel-doc -text -export "$file" 2>/dev/null) + str=$(scripts/kernel-doc -export "$file" 2>/dev/null) if [[ -n "$str" ]]; then echo "$file" fi diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index bf0bf9063aaf..1919c311c149 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -108,13 +108,13 @@ gen_btf() local bin_arch if ! [ -x "$(command -v ${PAHOLE})" ]; then - info "BTF" "${1}: pahole (${PAHOLE}) is not available" + echo >&2 "BTF: ${1}: pahole (${PAHOLE}) is not available" return 1 fi pahole_ver=$(${PAHOLE} --version | sed -E 's/v([0-9]+)\.([0-9]+)/\1\2/') if [ "${pahole_ver}" -lt "113" ]; then - info "BTF" "${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" + echo >&2 "BTF: ${1}: pahole version $(${PAHOLE} --version) is too old, need at least v1.13" return 1 fi @@ -180,9 +180,9 @@ mksysmap() ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2} } -sortextable() +sorttable() { - ${objtree}/scripts/sortextable ${1} + ${objtree}/scripts/sorttable ${1} } # Delete output files in case of error @@ -308,9 +308,12 @@ fi vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} -if [ -n "${CONFIG_BUILDTIME_EXTABLE_SORT}" ]; then - info SORTEX vmlinux - sortextable vmlinux +if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then + info SORTTAB vmlinux + if ! sorttable vmlinux; then + echo >&2 Failed to sort kernel tables + exit 1 + fi fi info SYSMAP System.map diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index 612268eabef4..7225107a9aaf 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -38,6 +38,10 @@ #define R_AARCH64_ABS64 257 #endif +#define R_ARM_PC24 1 +#define R_ARM_THM_CALL 10 +#define R_ARM_CALL 28 + static int fd_map; /* File descriptor for file being modified. */ static int mmap_failed; /* Boolean flag. */ static char gpfx; /* prefix for global symbol name (sometimes '_') */ @@ -418,6 +422,18 @@ static char const *already_has_rel_mcount = "success"; /* our work here is done! #define RECORD_MCOUNT_64 #include "recordmcount.h" +static int arm_is_fake_mcount(Elf32_Rel const *rp) +{ + switch (ELF32_R_TYPE(w(rp->r_info))) { + case R_ARM_THM_CALL: + case R_ARM_CALL: + case R_ARM_PC24: + return 0; + } + + return 1; +} + /* 64-bit EM_MIPS has weird ELF64_Rela.r_info. * http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf * We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] @@ -523,6 +539,7 @@ static int do_file(char const *const fname) altmcount = "__gnu_mcount_nc"; make_nop = make_nop_arm; rel_type_nop = R_ARM_NONE; + is_fake_mcount32 = arm_is_fake_mcount; gpfx = 0; break; case EM_AARCH64: diff --git a/scripts/sortextable.h b/scripts/sortextable.h deleted file mode 100644 index d4b3f6c40f02..000000000000 --- a/scripts/sortextable.h +++ /dev/null @@ -1,209 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * sortextable.h - * - * Copyright 2011 - 2012 Cavium, Inc. - * - * Some of this code was taken out of recordmcount.h written by: - * - * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. - * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. - */ - -#undef extable_ent_size -#undef compare_extable -#undef do_func -#undef Elf_Addr -#undef Elf_Ehdr -#undef Elf_Shdr -#undef Elf_Rel -#undef Elf_Rela -#undef Elf_Sym -#undef ELF_R_SYM -#undef Elf_r_sym -#undef ELF_R_INFO -#undef Elf_r_info -#undef ELF_ST_BIND -#undef ELF_ST_TYPE -#undef fn_ELF_R_SYM -#undef fn_ELF_R_INFO -#undef uint_t -#undef _r -#undef _w - -#ifdef SORTEXTABLE_64 -# define extable_ent_size 16 -# define compare_extable compare_extable_64 -# define do_func do64 -# define Elf_Addr Elf64_Addr -# define Elf_Ehdr Elf64_Ehdr -# define Elf_Shdr Elf64_Shdr -# define Elf_Rel Elf64_Rel -# define Elf_Rela Elf64_Rela -# define Elf_Sym Elf64_Sym -# define ELF_R_SYM ELF64_R_SYM -# define Elf_r_sym Elf64_r_sym -# define ELF_R_INFO ELF64_R_INFO -# define Elf_r_info Elf64_r_info -# define ELF_ST_BIND ELF64_ST_BIND -# define ELF_ST_TYPE ELF64_ST_TYPE -# define fn_ELF_R_SYM fn_ELF64_R_SYM -# define fn_ELF_R_INFO fn_ELF64_R_INFO -# define uint_t uint64_t -# define _r r8 -# define _w w8 -#else -# define extable_ent_size 8 -# define compare_extable compare_extable_32 -# define do_func do32 -# define Elf_Addr Elf32_Addr -# define Elf_Ehdr Elf32_Ehdr -# define Elf_Shdr Elf32_Shdr -# define Elf_Rel Elf32_Rel -# define Elf_Rela Elf32_Rela -# define Elf_Sym Elf32_Sym -# define ELF_R_SYM ELF32_R_SYM -# define Elf_r_sym Elf32_r_sym -# define ELF_R_INFO ELF32_R_INFO -# define Elf_r_info Elf32_r_info -# define ELF_ST_BIND ELF32_ST_BIND -# define ELF_ST_TYPE ELF32_ST_TYPE -# define fn_ELF_R_SYM fn_ELF32_R_SYM -# define fn_ELF_R_INFO fn_ELF32_R_INFO -# define uint_t uint32_t -# define _r r -# define _w w -#endif - -static int compare_extable(const void *a, const void *b) -{ - Elf_Addr av = _r(a); - Elf_Addr bv = _r(b); - - if (av < bv) - return -1; - if (av > bv) - return 1; - return 0; -} - -static void -do_func(Elf_Ehdr *ehdr, char const *const fname, table_sort_t custom_sort) -{ - Elf_Shdr *shdr; - Elf_Shdr *shstrtab_sec; - Elf_Shdr *strtab_sec = NULL; - 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; - int relocs_size = 0; - uint32_t *sort_done_location; - const char *secstrtab; - const char *strtab; - char *extab_image; - 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)); - - 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 < num_sections; i++) { - idx = r(&shdr[i].sh_name); - if (strcmp(secstrtab + idx, "__ex_table") == 0) { - extab_sec = shdr + i; - extab_index = i; - } - if ((r(&shdr[i].sh_type) == SHT_REL || - r(&shdr[i].sh_type) == SHT_RELA) && - r(&shdr[i].sh_info) == extab_index) { - relocs = (void *)ehdr + _r(&shdr[i].sh_offset); - relocs_size = _r(&shdr[i].sh_size); - } - if (strcmp(secstrtab + idx, ".symtab") == 0) - 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); - fail_file(); - } - if (symtab_sec == NULL) { - 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(); - } - strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); - - extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); - - if (custom_sort) { - custom_sort(extab_image, _r(&extab_sec->sh_size)); - } else { - int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; - qsort(extab_image, num_entries, - extable_ent_size, compare_extable); - } - /* If there were relocations, we no longer need them. */ - if (relocs) - memset(relocs, 0, relocs_size); - - /* find main_extable_sort_needed */ - sort_needed_sym = NULL; - for (i = 0; i < _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); i++) { - sym = (void *)ehdr + _r(&symtab_sec->sh_offset); - sym += i; - if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) - continue; - idx = r(&sym->st_name); - if (strcmp(strtab + idx, "main_extable_sort_needed") == 0) { - sort_needed_sym = sym; - break; - } - } - if (sort_needed_sym == NULL) { - fprintf(stderr, - "no main_extable_sort_needed symbol in file: %s\n", - fname); - fail_file(); - } - 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) - - _r(&sort_needed_sec->sh_addr); - -#if 0 - printf("sort done marker at %lx\n", - (unsigned long)((char *)sort_done_location - (char *)ehdr)); -#endif - /* We sorted it, clear the flag. */ - w(0, sort_done_location); -} diff --git a/scripts/sortextable.c b/scripts/sorttable.c index 55768654e3c6..ec6b5e81eba1 100644 --- a/scripts/sortextable.c +++ b/scripts/sorttable.c @@ -1,6 +1,10 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * sortextable.c: Sort the kernel's exception table + * sorttable.c: Sort the kernel's table + * + * Added ORC unwind tables sort support and other updates: + * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by: + * Shile Zhang <shile.zhang@linux.alibaba.com> * * Copyright 2011 - 2012 Cavium, Inc. * @@ -9,7 +13,7 @@ * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. * * Restructured to fit Linux format, as well as other updates: - * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. + * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. */ /* @@ -22,7 +26,6 @@ #include <getopt.h> #include <elf.h> #include <fcntl.h> -#include <setjmp.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -51,34 +54,13 @@ #define EM_ARCV2 195 #endif -static int fd_map; /* File descriptor for file being modified. */ -static int mmap_failed; /* Boolean flag. */ -static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */ -static struct stat sb; /* Remember .st_size, etc. */ -static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */ - -/* setjmp() return values */ -enum { - SJ_SETJMP = 0, /* hardwired first return */ - SJ_FAIL, - SJ_SUCCEED -}; - -/* Per-file resource cleanup when multiple files. */ -static void -cleanup(void) -{ - if (!mmap_failed) - munmap(ehdr_curr, sb.st_size); - close(fd_map); -} - -static void __attribute__((noreturn)) -fail_file(void) -{ - cleanup(); - longjmp(jmpenv, SJ_FAIL); -} +static uint32_t (*r)(const uint32_t *); +static uint16_t (*r2)(const uint16_t *); +static uint64_t (*r8)(const uint64_t *); +static void (*w)(uint32_t, uint32_t *); +static void (*w2)(uint16_t, uint16_t *); +static void (*w8)(uint64_t, uint64_t *); +typedef void (*table_sort_t)(char *, int); /* * Get the whole file as a programming convenience in order to avoid @@ -86,87 +68,98 @@ fail_file(void) * avoids copying unused pieces; else just read the whole file. * Open for both read and write. */ -static void *mmap_file(char const *fname) +static void *mmap_file(char const *fname, size_t *size) { - void *addr; + int fd; + struct stat sb; + void *addr = NULL; - fd_map = open(fname, O_RDWR); - if (fd_map < 0 || fstat(fd_map, &sb) < 0) { + fd = open(fname, O_RDWR); + if (fd < 0) { perror(fname); - fail_file(); + return NULL; + } + if (fstat(fd, &sb) < 0) { + perror(fname); + goto out; } if (!S_ISREG(sb.st_mode)) { fprintf(stderr, "not a regular file: %s\n", fname); - fail_file(); + goto out; } - addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, - fd_map, 0); + + addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (addr == MAP_FAILED) { - mmap_failed = 1; fprintf(stderr, "Could not mmap file: %s\n", fname); - fail_file(); + goto out; } + + *size = sb.st_size; + +out: + close(fd); return addr; } -static uint64_t r8be(const uint64_t *x) -{ - return get_unaligned_be64(x); -} static uint32_t rbe(const uint32_t *x) { return get_unaligned_be32(x); } + static uint16_t r2be(const uint16_t *x) { return get_unaligned_be16(x); } -static uint64_t r8le(const uint64_t *x) + +static uint64_t r8be(const uint64_t *x) { - return get_unaligned_le64(x); + return get_unaligned_be64(x); } + static uint32_t rle(const uint32_t *x) { return get_unaligned_le32(x); } + static uint16_t r2le(const uint16_t *x) { return get_unaligned_le16(x); } -static void w8be(uint64_t val, uint64_t *x) +static uint64_t r8le(const uint64_t *x) { - put_unaligned_be64(val, x); + return get_unaligned_le64(x); } + static void wbe(uint32_t val, uint32_t *x) { put_unaligned_be32(val, x); } + static void w2be(uint16_t val, uint16_t *x) { put_unaligned_be16(val, x); } -static void w8le(uint64_t val, uint64_t *x) + +static void w8be(uint64_t val, uint64_t *x) { - put_unaligned_le64(val, x); + put_unaligned_be64(val, x); } + static void wle(uint32_t val, uint32_t *x) { put_unaligned_le32(val, x); } + static void w2le(uint16_t val, uint16_t *x) { put_unaligned_le16(val, x); } -static uint64_t (*r8)(const uint64_t *); -static uint32_t (*r)(const uint32_t *); -static uint16_t (*r2)(const uint16_t *); -static void (*w8)(uint64_t, uint64_t *); -static void (*w)(uint32_t, uint32_t *); -static void (*w2)(uint16_t, uint16_t *); - -typedef void (*table_sort_t)(char *, int); +static void w8le(uint64_t val, uint64_t *x) +{ + put_unaligned_le64(val, x); +} /* * Move reserved section indices SHN_LORESERVE..SHN_HIRESERVE out of @@ -193,9 +186,9 @@ static inline unsigned int get_secindex(unsigned int shndx, } /* 32 bit and 64 bit are very similar */ -#include "sortextable.h" -#define SORTEXTABLE_64 -#include "sortextable.h" +#include "sorttable.h" +#define SORTTABLE_64 +#include "sorttable.h" static int compare_relative_table(const void *a, const void *b) { @@ -209,110 +202,100 @@ static int compare_relative_table(const void *a, const void *b) return 0; } -static void x86_sort_relative_table(char *extab_image, int image_size) +static void sort_relative_table(char *extab_image, int image_size) { - int i; + int i = 0; - i = 0; + /* + * Do the same thing the runtime sort does, first normalize to + * being relative to the start of the section. + */ while (i < image_size) { uint32_t *loc = (uint32_t *)(extab_image + i); - w(r(loc) + i, loc); - w(r(loc + 1) + i + 4, loc + 1); - w(r(loc + 2) + i + 8, loc + 2); - - i += sizeof(uint32_t) * 3; + i += 4; } - qsort(extab_image, image_size / 12, 12, compare_relative_table); + qsort(extab_image, image_size / 8, 8, compare_relative_table); + /* Now denormalize. */ i = 0; while (i < image_size) { uint32_t *loc = (uint32_t *)(extab_image + i); - w(r(loc) - i, loc); - w(r(loc + 1) - (i + 4), loc + 1); - w(r(loc + 2) - (i + 8), loc + 2); - - i += sizeof(uint32_t) * 3; + i += 4; } } -static void sort_relative_table(char *extab_image, int image_size) +static void x86_sort_relative_table(char *extab_image, int image_size) { - int i; + int i = 0; - /* - * Do the same thing the runtime sort does, first normalize to - * being relative to the start of the section. - */ - i = 0; while (i < image_size) { uint32_t *loc = (uint32_t *)(extab_image + i); + w(r(loc) + i, loc); - i += 4; + w(r(loc + 1) + i + 4, loc + 1); + w(r(loc + 2) + i + 8, loc + 2); + + i += sizeof(uint32_t) * 3; } - qsort(extab_image, image_size / 8, 8, compare_relative_table); + qsort(extab_image, image_size / 12, 12, compare_relative_table); - /* Now denormalize. */ i = 0; while (i < image_size) { uint32_t *loc = (uint32_t *)(extab_image + i); + w(r(loc) - i, loc); - i += 4; + w(r(loc + 1) - (i + 4), loc + 1); + w(r(loc + 2) - (i + 8), loc + 2); + + i += sizeof(uint32_t) * 3; } } -static void -do_file(char const *const fname) +static int do_file(char const *const fname, void *addr) { - table_sort_t custom_sort; - Elf32_Ehdr *ehdr = mmap_file(fname); + int rc = -1; + Elf32_Ehdr *ehdr = addr; + table_sort_t custom_sort = NULL; - ehdr_curr = ehdr; switch (ehdr->e_ident[EI_DATA]) { - default: - fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", - ehdr->e_ident[EI_DATA], fname); - fail_file(); - break; case ELFDATA2LSB: - r = rle; - r2 = r2le; - r8 = r8le; - w = wle; - w2 = w2le; - w8 = w8le; + r = rle; + r2 = r2le; + r8 = r8le; + w = wle; + w2 = w2le; + w8 = w8le; break; case ELFDATA2MSB: - r = rbe; - r2 = r2be; - r8 = r8be; - w = wbe; - w2 = w2be; - w8 = w8be; + r = rbe; + r2 = r2be; + r8 = r8be; + w = wbe; + w2 = w2be; + w8 = w8be; break; - } /* end switch */ - if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 - || (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) - || ehdr->e_ident[EI_VERSION] != EV_CURRENT) { + default: + fprintf(stderr, "unrecognized ELF data encoding %d: %s\n", + ehdr->e_ident[EI_DATA], fname); + return -1; + } + + if (memcmp(ELFMAG, ehdr->e_ident, SELFMAG) != 0 || + (r2(&ehdr->e_type) != ET_EXEC && r2(&ehdr->e_type) != ET_DYN) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT) { fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file %s\n", fname); - fail_file(); + return -1; } - custom_sort = NULL; switch (r2(&ehdr->e_machine)) { - default: - fprintf(stderr, "unrecognized e_machine %d %s\n", - r2(&ehdr->e_machine), fname); - fail_file(); - break; case EM_386: case EM_X86_64: custom_sort = x86_sort_relative_table; break; - case EM_S390: case EM_AARCH64: case EM_PARISC: @@ -327,74 +310,68 @@ do_file(char const *const fname) case EM_MIPS: case EM_XTENSA: break; - } /* end switch */ + default: + fprintf(stderr, "unrecognized e_machine %d %s\n", + r2(&ehdr->e_machine), fname); + return -1; + } switch (ehdr->e_ident[EI_CLASS]) { - default: - fprintf(stderr, "unrecognized ELF class %d %s\n", - ehdr->e_ident[EI_CLASS], fname); - fail_file(); - break; case ELFCLASS32: - if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) - || r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { + if (r2(&ehdr->e_ehsize) != sizeof(Elf32_Ehdr) || + r2(&ehdr->e_shentsize) != sizeof(Elf32_Shdr)) { fprintf(stderr, "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); - fail_file(); + break; } - do32(ehdr, fname, custom_sort); + rc = do_sort_32(ehdr, fname, custom_sort); break; - case ELFCLASS64: { + case ELFCLASS64: + { Elf64_Ehdr *const ghdr = (Elf64_Ehdr *)ehdr; - if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) - || r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { + if (r2(&ghdr->e_ehsize) != sizeof(Elf64_Ehdr) || + r2(&ghdr->e_shentsize) != sizeof(Elf64_Shdr)) { fprintf(stderr, - "unrecognized ET_EXEC/ET_DYN file: %s\n", fname); - fail_file(); + "unrecognized ET_EXEC/ET_DYN file: %s\n", + fname); + break; + } + rc = do_sort_64(ghdr, fname, custom_sort); } - do64(ghdr, fname, custom_sort); + break; + default: + fprintf(stderr, "unrecognized ELF class %d %s\n", + ehdr->e_ident[EI_CLASS], fname); break; } - } /* end switch */ - cleanup(); + return rc; } -int -main(int argc, char *argv[]) +int main(int argc, char *argv[]) { - int n_error = 0; /* gcc-4.3.0 false positive complaint */ - int i; + int i, n_error = 0; /* gcc-4.3.0 false positive complaint */ + size_t size = 0; + void *addr = NULL; if (argc < 2) { - fprintf(stderr, "usage: sortextable vmlinux...\n"); + fprintf(stderr, "usage: sorttable vmlinux...\n"); return 0; } /* Process each file in turn, allowing deep failure. */ for (i = 1; i < argc; i++) { - char *file = argv[i]; - int const sjval = setjmp(jmpenv); + addr = mmap_file(argv[i], &size); + if (!addr) { + ++n_error; + continue; + } - switch (sjval) { - default: - fprintf(stderr, "internal error: %s\n", file); - exit(1); - break; - case SJ_SETJMP: /* normal sequence */ - /* Avoid problems if early cleanup() */ - fd_map = -1; - ehdr_curr = NULL; - mmap_failed = 1; - do_file(file); - break; - case SJ_FAIL: /* error in do_file or below */ + if (do_file(argv[i], addr)) ++n_error; - break; - case SJ_SUCCEED: /* premature success */ - /* do nothing */ - break; - } /* end switch */ + + munmap(addr, size); } + return !!n_error; } diff --git a/scripts/sorttable.h b/scripts/sorttable.h new file mode 100644 index 000000000000..a2baa2fefb13 --- /dev/null +++ b/scripts/sorttable.h @@ -0,0 +1,380 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * sorttable.h + * + * Added ORC unwind tables sort support and other updates: + * Copyright (C) 1999-2019 Alibaba Group Holding Limited. by: + * Shile Zhang <shile.zhang@linux.alibaba.com> + * + * Copyright 2011 - 2012 Cavium, Inc. + * + * Some of code was taken out of arch/x86/kernel/unwind_orc.c, written by: + * Copyright (C) 2017 Josh Poimboeuf <jpoimboe@redhat.com> + * + * Some of this code was taken out of recordmcount.h written by: + * + * Copyright 2009 John F. Reiser <jreiser@BitWagon.com>. All rights reserved. + * Copyright 2010 Steven Rostedt <srostedt@redhat.com>, Red Hat Inc. + */ + +#undef extable_ent_size +#undef compare_extable +#undef do_sort +#undef Elf_Addr +#undef Elf_Ehdr +#undef Elf_Shdr +#undef Elf_Rel +#undef Elf_Rela +#undef Elf_Sym +#undef ELF_R_SYM +#undef Elf_r_sym +#undef ELF_R_INFO +#undef Elf_r_info +#undef ELF_ST_BIND +#undef ELF_ST_TYPE +#undef fn_ELF_R_SYM +#undef fn_ELF_R_INFO +#undef uint_t +#undef _r +#undef _w + +#ifdef SORTTABLE_64 +# define extable_ent_size 16 +# define compare_extable compare_extable_64 +# define do_sort do_sort_64 +# define Elf_Addr Elf64_Addr +# define Elf_Ehdr Elf64_Ehdr +# define Elf_Shdr Elf64_Shdr +# define Elf_Rel Elf64_Rel +# define Elf_Rela Elf64_Rela +# define Elf_Sym Elf64_Sym +# define ELF_R_SYM ELF64_R_SYM +# define Elf_r_sym Elf64_r_sym +# define ELF_R_INFO ELF64_R_INFO +# define Elf_r_info Elf64_r_info +# define ELF_ST_BIND ELF64_ST_BIND +# define ELF_ST_TYPE ELF64_ST_TYPE +# define fn_ELF_R_SYM fn_ELF64_R_SYM +# define fn_ELF_R_INFO fn_ELF64_R_INFO +# define uint_t uint64_t +# define _r r8 +# define _w w8 +#else +# define extable_ent_size 8 +# define compare_extable compare_extable_32 +# define do_sort do_sort_32 +# define Elf_Addr Elf32_Addr +# define Elf_Ehdr Elf32_Ehdr +# define Elf_Shdr Elf32_Shdr +# define Elf_Rel Elf32_Rel +# define Elf_Rela Elf32_Rela +# define Elf_Sym Elf32_Sym +# define ELF_R_SYM ELF32_R_SYM +# define Elf_r_sym Elf32_r_sym +# define ELF_R_INFO ELF32_R_INFO +# define Elf_r_info Elf32_r_info +# define ELF_ST_BIND ELF32_ST_BIND +# define ELF_ST_TYPE ELF32_ST_TYPE +# define fn_ELF_R_SYM fn_ELF32_R_SYM +# define fn_ELF_R_INFO fn_ELF32_R_INFO +# define uint_t uint32_t +# define _r r +# define _w w +#endif + +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) +/* ORC unwinder only support X86_64 */ +#include <errno.h> +#include <pthread.h> +#include <asm/orc_types.h> + +#define ERRSTR_MAXSZ 256 + +char g_err[ERRSTR_MAXSZ]; +int *g_orc_ip_table; +struct orc_entry *g_orc_table; + +pthread_t orc_sort_thread; + +static inline unsigned long orc_ip(const int *ip) +{ + return (unsigned long)ip + *ip; +} + +static int orc_sort_cmp(const void *_a, const void *_b) +{ + struct orc_entry *orc_a; + const int *a = g_orc_ip_table + *(int *)_a; + const int *b = g_orc_ip_table + *(int *)_b; + unsigned long a_val = orc_ip(a); + unsigned long b_val = orc_ip(b); + + if (a_val > b_val) + return 1; + if (a_val < b_val) + return -1; + + /* + * The "weak" section terminator entries need to always be on the left + * to ensure the lookup code skips them in favor of real entries. + * These terminator entries exist to handle any gaps created by + * whitelisted .o files which didn't get objtool generation. + */ + orc_a = g_orc_table + (a - g_orc_ip_table); + return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1; +} + +static void *sort_orctable(void *arg) +{ + int i; + int *idxs = NULL; + int *tmp_orc_ip_table = NULL; + struct orc_entry *tmp_orc_table = NULL; + unsigned int *orc_ip_size = (unsigned int *)arg; + unsigned int num_entries = *orc_ip_size / sizeof(int); + unsigned int orc_size = num_entries * sizeof(struct orc_entry); + + idxs = (int *)malloc(*orc_ip_size); + if (!idxs) { + snprintf(g_err, ERRSTR_MAXSZ, "malloc idxs: %s", + strerror(errno)); + pthread_exit(g_err); + } + + tmp_orc_ip_table = (int *)malloc(*orc_ip_size); + if (!tmp_orc_ip_table) { + snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_ip_table: %s", + strerror(errno)); + pthread_exit(g_err); + } + + tmp_orc_table = (struct orc_entry *)malloc(orc_size); + if (!tmp_orc_table) { + snprintf(g_err, ERRSTR_MAXSZ, "malloc tmp_orc_table: %s", + strerror(errno)); + pthread_exit(g_err); + } + + /* initialize indices array, convert ip_table to absolute address */ + for (i = 0; i < num_entries; i++) { + idxs[i] = i; + tmp_orc_ip_table[i] = g_orc_ip_table[i] + i * sizeof(int); + } + memcpy(tmp_orc_table, g_orc_table, orc_size); + + qsort(idxs, num_entries, sizeof(int), orc_sort_cmp); + + for (i = 0; i < num_entries; i++) { + if (idxs[i] == i) + continue; + + /* convert back to relative address */ + g_orc_ip_table[i] = tmp_orc_ip_table[idxs[i]] - i * sizeof(int); + g_orc_table[i] = tmp_orc_table[idxs[i]]; + } + + free(idxs); + free(tmp_orc_ip_table); + free(tmp_orc_table); + pthread_exit(NULL); +} +#endif + +static int compare_extable(const void *a, const void *b) +{ + Elf_Addr av = _r(a); + Elf_Addr bv = _r(b); + + if (av < bv) + return -1; + if (av > bv) + return 1; + return 0; +} + +static int do_sort(Elf_Ehdr *ehdr, + char const *const fname, + table_sort_t custom_sort) +{ + int rc = -1; + Elf_Shdr *s, *shdr = (Elf_Shdr *)((char *)ehdr + _r(&ehdr->e_shoff)); + Elf_Shdr *strtab_sec = NULL; + Elf_Shdr *symtab_sec = NULL; + Elf_Shdr *extab_sec = NULL; + Elf_Sym *sym; + const Elf_Sym *symtab; + Elf32_Word *symtab_shndx = NULL; + Elf_Sym *sort_needed_sym = NULL; + Elf_Shdr *sort_needed_sec; + Elf_Rel *relocs = NULL; + int relocs_size = 0; + uint32_t *sort_needed_loc; + const char *secstrings; + const char *strtab; + char *extab_image; + int extab_index = 0; + int i; + int idx; + unsigned int shnum; + unsigned int shstrndx; +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + unsigned int orc_ip_size = 0; + unsigned int orc_size = 0; + unsigned int orc_num_entries = 0; +#endif + + shstrndx = r2(&ehdr->e_shstrndx); + if (shstrndx == SHN_XINDEX) + shstrndx = r(&shdr[0].sh_link); + secstrings = (const char *)ehdr + _r(&shdr[shstrndx].sh_offset); + + shnum = r2(&ehdr->e_shnum); + if (shnum == SHN_UNDEF) + shnum = _r(&shdr[0].sh_size); + + for (i = 0, s = shdr; s < shdr + shnum; i++, s++) { + idx = r(&s->sh_name); + if (!strcmp(secstrings + idx, "__ex_table")) { + extab_sec = s; + extab_index = i; + } + if (!strcmp(secstrings + idx, ".symtab")) + symtab_sec = s; + if (!strcmp(secstrings + idx, ".strtab")) + strtab_sec = s; + + if ((r(&s->sh_type) == SHT_REL || + r(&s->sh_type) == SHT_RELA) && + r(&s->sh_info) == extab_index) { + relocs = (void *)ehdr + _r(&s->sh_offset); + relocs_size = _r(&s->sh_size); + } + if (r(&s->sh_type) == SHT_SYMTAB_SHNDX) + symtab_shndx = (Elf32_Word *)((const char *)ehdr + + _r(&s->sh_offset)); + +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + /* locate the ORC unwind tables */ + if (!strcmp(secstrings + idx, ".orc_unwind_ip")) { + orc_ip_size = s->sh_size; + g_orc_ip_table = (int *)((void *)ehdr + + s->sh_offset); + } + if (!strcmp(secstrings + idx, ".orc_unwind")) { + orc_size = s->sh_size; + g_orc_table = (struct orc_entry *)((void *)ehdr + + s->sh_offset); + } +#endif + } /* for loop */ + +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + if (!g_orc_ip_table || !g_orc_table) { + fprintf(stderr, + "incomplete ORC unwind tables in file: %s\n", fname); + goto out; + } + + orc_num_entries = orc_ip_size / sizeof(int); + if (orc_ip_size % sizeof(int) != 0 || + orc_size % sizeof(struct orc_entry) != 0 || + orc_num_entries != orc_size / sizeof(struct orc_entry)) { + fprintf(stderr, + "inconsistent ORC unwind table entries in file: %s\n", + fname); + goto out; + } + + /* create thread to sort ORC unwind tables concurrently */ + if (pthread_create(&orc_sort_thread, NULL, + sort_orctable, &orc_ip_size)) { + fprintf(stderr, + "pthread_create orc_sort_thread failed '%s': %s\n", + strerror(errno), fname); + goto out; + } +#endif + if (!extab_sec) { + fprintf(stderr, "no __ex_table in file: %s\n", fname); + goto out; + } + + if (!symtab_sec) { + fprintf(stderr, "no .symtab in file: %s\n", fname); + goto out; + } + + if (!strtab_sec) { + fprintf(stderr, "no .strtab in file: %s\n", fname); + goto out; + } + + extab_image = (void *)ehdr + _r(&extab_sec->sh_offset); + strtab = (const char *)ehdr + _r(&strtab_sec->sh_offset); + symtab = (const Elf_Sym *)((const char *)ehdr + + _r(&symtab_sec->sh_offset)); + + if (custom_sort) { + custom_sort(extab_image, _r(&extab_sec->sh_size)); + } else { + int num_entries = _r(&extab_sec->sh_size) / extable_ent_size; + qsort(extab_image, num_entries, + extable_ent_size, compare_extable); + } + + /* If there were relocations, we no longer need them. */ + if (relocs) + memset(relocs, 0, relocs_size); + + /* find the flag main_extable_sort_needed */ + for (sym = (void *)ehdr + _r(&symtab_sec->sh_offset); + sym < sym + _r(&symtab_sec->sh_size) / sizeof(Elf_Sym); + sym++) { + if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT) + continue; + if (!strcmp(strtab + r(&sym->st_name), + "main_extable_sort_needed")) { + sort_needed_sym = sym; + break; + } + } + + if (!sort_needed_sym) { + fprintf(stderr, + "no main_extable_sort_needed symbol in file: %s\n", + fname); + goto out; + } + + sort_needed_sec = &shdr[get_secindex(r2(&sym->st_shndx), + sort_needed_sym - symtab, + symtab_shndx)]; + sort_needed_loc = (void *)ehdr + + _r(&sort_needed_sec->sh_offset) + + _r(&sort_needed_sym->st_value) - + _r(&sort_needed_sec->sh_addr); + + /* extable has been sorted, clear the flag */ + w(0, sort_needed_loc); + rc = 0; + +out: +#if defined(SORTTABLE_64) && defined(UNWINDER_ORC_ENABLED) + if (orc_sort_thread) { + void *retval = NULL; + /* wait for ORC tables sort done */ + rc = pthread_join(orc_sort_thread, &retval); + if (rc) + fprintf(stderr, + "pthread_join failed '%s': %s\n", + strerror(errno), fname); + else if (retval) { + rc = -1; + fprintf(stderr, + "failed to sort ORC tables '%s': %s\n", + (char *)retval, fname); + } + } +#endif + return rc; +} diff --git a/scripts/spelling.txt b/scripts/spelling.txt index 672b5931bc8d..ffa838f3a2b5 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -39,6 +39,8 @@ accout||account accquire||acquire accquired||acquired accross||across +accumalate||accumulate +accumalator||accumulator acessable||accessible acess||access acessing||accessing @@ -106,6 +108,7 @@ alogrithm||algorithm alot||a lot alow||allow alows||allows +alreay||already alredy||already altough||although alue||value @@ -241,6 +244,7 @@ calender||calendar calescing||coalescing calle||called callibration||calibration +callled||called calucate||calculate calulate||calculate cancelation||cancellation @@ -311,6 +315,7 @@ compaibility||compatibility comparsion||comparison compatability||compatibility compatable||compatible +compatibililty||compatibility compatibiliy||compatibility compatibilty||compatibility compatiblity||compatibility @@ -330,6 +335,7 @@ comunication||communication conbination||combination conditionaly||conditionally conditon||condition +condtion||condition conected||connected conector||connector connecetd||connected @@ -388,6 +394,8 @@ dafault||default deafult||default deamon||daemon debouce||debounce +decendant||descendant +decendants||descendants decompres||decompress decsribed||described decription||description @@ -411,11 +419,13 @@ delare||declare delares||declares delaring||declaring delemiter||delimiter +delievered||delivered demodualtor||demodulator demension||dimension dependancies||dependencies dependancy||dependency dependant||dependent +dependend||dependent depreacted||deprecated depreacte||deprecate desactivate||deactivate @@ -791,6 +801,7 @@ ireelevant||irrelevant irrelevent||irrelevant isnt||isn't isssue||issue +issus||issues iternations||iterations itertation||iteration itslef||itself @@ -995,6 +1006,7 @@ peice||piece pendantic||pedantic peprocessor||preprocessor perfoming||performing +perfomring||performing peripherial||peripheral permissons||permissions peroid||period @@ -1166,6 +1178,8 @@ retreive||retrieve retreiving||retrieving retrive||retrieve retrived||retrieved +retrun||return +retun||return retuned||returned reudce||reduce reuest||request |