Index: head/contrib/elftoolchain/addr2line/addr2line.c =================================================================== --- head/contrib/elftoolchain/addr2line/addr2line.c (revision 280931) +++ head/contrib/elftoolchain/addr2line/addr2line.c (revision 280932) @@ -1,412 +1,411 @@ /*- * Copyright (c) 2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: addr2line.c 3148 2015-02-15 18:47:39Z emaste $"); +ELFTC_VCSID("$Id: addr2line.c 3174 2015-03-27 17:13:41Z emaste $"); static struct option longopts[] = { {"target" , required_argument, NULL, 'b'}, {"demangle", no_argument, NULL, 'C'}, {"exe", required_argument, NULL, 'e'}, {"functions", no_argument, NULL, 'f'}, {"section", required_argument, NULL, 'j'}, {"basename", no_argument, NULL, 's'}, {"help", no_argument, NULL, 'H'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; static int demangle, func, base; static char unknown[] = { '?', '?', '\0' }; static Dwarf_Addr section_base; #define USAGE_MESSAGE "\ Usage: %s [options] hexaddress...\n\ Map program addresses to source file names and line numbers.\n\n\ Options:\n\ -b TGT | --target=TGT (Accepted but ignored).\n\ -e EXE | --exec=EXE Use program \"EXE\" to translate addresses.\n\ -f | --functions Display function names.\n\ -j NAME | --section=NAME Values are offsets into section \"NAME\".\n\ -s | --basename Only show the base name for each file name.\n\ -C | --demangle Demangle C++ names.\n\ -H | --help Print a help message.\n\ -V | --version Print a version identifier and exit.\n" static void usage(void) { (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(1); } static void version(void) { fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(0); } static void search_func(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Addr addr, const char **rlt_func) { Dwarf_Die ret_die, spec_die; Dwarf_Error de; Dwarf_Half tag; Dwarf_Unsigned lopc, hipc; Dwarf_Off ref; Dwarf_Attribute sub_at, spec_at; char *func0; int ret; if (*rlt_func != NULL) return; if (dwarf_tag(die, &tag, &de)) { warnx("dwarf_tag: %s", dwarf_errmsg(de)); goto cont_search; } if (tag == DW_TAG_subprogram) { if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) || dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) goto cont_search; if (addr < lopc || addr >= hipc) goto cont_search; /* Found it! */ *rlt_func = unknown; ret = dwarf_attr(die, DW_AT_name, &sub_at, &de); if (ret == DW_DLV_ERROR) return; if (ret == DW_DLV_OK) { if (dwarf_formstring(sub_at, &func0, &de)) *rlt_func = unknown; else *rlt_func = func0; return; } /* * If DW_AT_name is not present, but DW_AT_specification is * present, then probably the actual name is in the DIE * referenced by DW_AT_specification. */ if (dwarf_attr(die, DW_AT_specification, &spec_at, &de)) return; if (dwarf_global_formref(spec_at, &ref, &de)) return; if (dwarf_offdie(dbg, ref, &spec_die, &de)) return; if (dwarf_attrval_string(spec_die, DW_AT_name, rlt_func, &de)) *rlt_func = unknown; return; } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); /* Search sibling. */ ret = dwarf_siblingof(dbg, die, &ret_die, &de); if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_func(dbg, ret_die, addr, rlt_func); } static void translate(Dwarf_Debug dbg, const char* addrstr) { Dwarf_Die die; Dwarf_Line *lbuf; Dwarf_Error de; Dwarf_Half tag; Dwarf_Unsigned lopc, hipc, addr, lineno, plineno; Dwarf_Signed lcount; Dwarf_Addr lineaddr, plineaddr; const char *funcname; char *file, *file0, *pfile; char demangled[1024]; int i, ret; addr = strtoull(addrstr, NULL, 16); addr += section_base; lineno = 0; file = unknown; while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); goto out; } /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } if (die == NULL) { warnx("could not find DW_TAG_compile_unit die"); goto out; } if (!dwarf_attrval_unsigned(die, DW_AT_low_pc, &lopc, &de) && !dwarf_attrval_unsigned(die, DW_AT_high_pc, &hipc, &de)) { /* * Check if the address falls into the PC range of * this CU. */ if (addr < lopc || addr >= hipc) continue; } if (dwarf_srclines(die, &lbuf, &lcount, &de) != DW_DLV_OK) { warnx("dwarf_srclines: %s", dwarf_errmsg(de)); goto out; } plineaddr = ~0ULL; plineno = 0; pfile = unknown; for (i = 0; i < lcount; i++) { if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { warnx("dwarf_lineaddr: %s", dwarf_errmsg(de)); goto out; } if (dwarf_lineno(lbuf[i], &lineno, &de)) { warnx("dwarf_lineno: %s", dwarf_errmsg(de)); goto out; } if (dwarf_linesrc(lbuf[i], &file0, &de)) { warnx("dwarf_linesrc: %s", dwarf_errmsg(de)); } else file = file0; if (addr == lineaddr) goto out; else if (addr < lineaddr && addr > plineaddr) { lineno = plineno; file = pfile; goto out; } plineaddr = lineaddr; plineno = lineno; pfile = file; } } out: funcname = NULL; if (ret == DW_DLV_OK && func) search_func(dbg, die, addr, &funcname); if (func) { if (funcname == NULL) funcname = unknown; if (demangle && !elftc_demangle(funcname, demangled, sizeof(demangled), 0)) printf("%s\n", demangled); else printf("%s\n", funcname); } (void) printf("%s:%ju\n", base ? basename(file) : file, lineno); /* * Reset internal CU pointer, so we will start from the first CU * next round. */ while (ret != DW_DLV_NO_ENTRY) { if (ret == DW_DLV_ERROR) errx(EXIT_FAILURE, "dwarf_next_cu_header: %s", dwarf_errmsg(de)); ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de); } } static void find_section_base(const char *exe, Elf *e, const char *section) { Dwarf_Addr off; Elf_Scn *scn; GElf_Ehdr eh; GElf_Shdr sh; size_t shstrndx; int elferr; const char *name; if (gelf_getehdr(e, &eh) != &eh) { warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); return; } if (!elf_getshstrndx(e, &shstrndx)) { warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); return; } (void) elf_errno(); off = 0; scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); continue; } if ((name = elf_strptr(e, shstrndx, sh.sh_name)) == NULL) goto next; if (!strcmp(section, name)) { if (eh.e_type == ET_EXEC || eh.e_type == ET_DYN) { /* * For executables, section base is the virtual * address of the specified section. */ section_base = sh.sh_addr; } else if (eh.e_type == ET_REL) { /* * For relocatables, section base is the * relative offset of the specified section * to the start of the first section. */ section_base = off; } else warnx("unknown e_type %u", eh.e_type); return; } next: off += sh.sh_size; } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); errx(EXIT_FAILURE, "%s: cannot find section %s", exe, section); } int main(int argc, char **argv) { Elf *e; Dwarf_Debug dbg; Dwarf_Error de; const char *exe, *section; char line[1024]; int fd, i, opt; exe = NULL; section = NULL; while ((opt = getopt_long(argc, argv, "b:Ce:fj:sHV", longopts, NULL)) != -1) { switch (opt) { case 'b': /* ignored */ break; case 'C': demangle = 1; break; case 'e': exe = optarg; break; case 'f': func = 1; break; case 'j': section = optarg; break; case 's': base = 1; break; case 'H': usage(); case 'V': version(); default: usage(); } } argv += optind; argc -= optind; if (exe == NULL) exe = "a.out"; if ((fd = open(exe, O_RDONLY)) < 0) err(EXIT_FAILURE, "%s", exe); if (dwarf_init(fd, DW_DLC_READ, NULL, NULL, &dbg, &de)) errx(EXIT_FAILURE, "dwarf_init: %s", dwarf_errmsg(de)); if (dwarf_get_elf(dbg, &e, &de) != DW_DLV_OK) errx(EXIT_FAILURE, "dwarf_get_elf: %s", dwarf_errmsg(de)); if (section) find_section_base(exe, e, section); else section_base = 0; if (argc > 0) for (i = 0; i < argc; i++) translate(dbg, argv[i]); else while (fgets(line, sizeof(line), stdin) != NULL) { translate(dbg, line); fflush(stdout); } dwarf_finish(dbg, &de); (void) elf_end(e); exit(0); } Index: head/contrib/elftoolchain/common/_elftc.h =================================================================== --- head/contrib/elftoolchain/common/_elftc.h (revision 280931) +++ head/contrib/elftoolchain/common/_elftc.h (revision 280932) @@ -1,465 +1,481 @@ /*- * Copyright (c) 2009 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _elftc.h 3139 2015-01-05 03:17:06Z kaiwang27 $ + * $Id: _elftc.h 3175 2015-03-27 17:21:24Z emaste $ */ /** ** Miscellanous definitions needed by multiple components. **/ #ifndef _ELFTC_H #define _ELFTC_H #ifndef NULL #define NULL ((void *) 0) #endif #ifndef offsetof #define offsetof(T, M) ((int) &((T*) 0) -> M) #endif /* --QUEUE-MACROS-- [[ */ /* * Supply macros missing from */ /* * Copyright (c) 1991, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef LIST_FOREACH_SAFE #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) #endif #ifndef SLIST_FOREACH_SAFE #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) #endif #ifndef STAILQ_CONCAT #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_EMPTY #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #endif #ifndef STAILQ_ENTRY #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } #endif #ifndef STAILQ_FIRST #define STAILQ_FIRST(head) ((head)->stqh_first) #endif #ifndef STAILQ_HEAD #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first; /* first element */ \ struct type **stqh_last; /* addr of last next element */ \ } #endif #ifndef STAILQ_HEAD_INITIALIZER #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #endif #ifndef STAILQ_FOREACH #define STAILQ_FOREACH(var, head, field) \ for ((var) = ((head)->stqh_first); \ (var); \ (var) = ((var)->field.stqe_next)) #endif #ifndef STAILQ_FOREACH_SAFE #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #endif #ifndef STAILQ_INIT #define STAILQ_INIT(head) do { \ (head)->stqh_first = NULL; \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_INSERT_HEAD #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ (head)->stqh_last = &(elm)->field.stqe_next; \ (head)->stqh_first = (elm); \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_INSERT_TAIL #define STAILQ_INSERT_TAIL(head, elm, field) do { \ (elm)->field.stqe_next = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &(elm)->field.stqe_next; \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_INSERT_AFTER #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\ (head)->stqh_last = &(elm)->field.stqe_next; \ (listelm)->field.stqe_next = (elm); \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_LAST #define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? \ NULL : ((struct type *)(void *) \ ((char *)((head)->stqh_last) - offsetof(struct type, field)))) #endif #ifndef STAILQ_NEXT #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #endif #ifndef STAILQ_REMOVE #define STAILQ_REMOVE(head, elm, type, field) do { \ if ((head)->stqh_first == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } else { \ struct type *curelm = (head)->stqh_first; \ while (curelm->field.stqe_next != (elm)) \ curelm = curelm->field.stqe_next; \ if ((curelm->field.stqe_next = \ curelm->field.stqe_next->field.stqe_next) == NULL) \ (head)->stqh_last = &(curelm)->field.stqe_next; \ } \ } while (/*CONSTCOND*/0) #endif #ifndef STAILQ_REMOVE_HEAD #define STAILQ_REMOVE_HEAD(head, field) do { \ if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == \ NULL) \ (head)->stqh_last = &(head)->stqh_first; \ } while (/*CONSTCOND*/0) #endif /* * The STAILQ_SORT macro is adapted from Simon Tatham's O(n*log(n)) * mergesort algorithm. */ #ifndef STAILQ_SORT #define STAILQ_SORT(head, type, field, cmp) do { \ STAILQ_HEAD(, type) _la, _lb; \ struct type *_p, *_q, *_e; \ int _i, _sz, _nmerges, _psz, _qsz; \ \ _sz = 1; \ do { \ _nmerges = 0; \ STAILQ_INIT(&_lb); \ while (!STAILQ_EMPTY((head))) { \ _nmerges++; \ STAILQ_INIT(&_la); \ _psz = 0; \ for (_i = 0; _i < _sz && !STAILQ_EMPTY((head)); \ _i++) { \ _e = STAILQ_FIRST((head)); \ if (_e == NULL) \ break; \ _psz++; \ STAILQ_REMOVE_HEAD((head), field); \ STAILQ_INSERT_TAIL(&_la, _e, field); \ } \ _p = STAILQ_FIRST(&_la); \ _qsz = _sz; \ _q = STAILQ_FIRST((head)); \ while (_psz > 0 || (_qsz > 0 && _q != NULL)) { \ if (_psz == 0) { \ _e = _q; \ _q = STAILQ_NEXT(_q, field); \ STAILQ_REMOVE_HEAD((head), \ field); \ _qsz--; \ } else if (_qsz == 0 || _q == NULL) { \ _e = _p; \ _p = STAILQ_NEXT(_p, field); \ STAILQ_REMOVE_HEAD(&_la, field);\ _psz--; \ } else if (cmp(_p, _q) <= 0) { \ _e = _p; \ _p = STAILQ_NEXT(_p, field); \ STAILQ_REMOVE_HEAD(&_la, field);\ _psz--; \ } else { \ _e = _q; \ _q = STAILQ_NEXT(_q, field); \ STAILQ_REMOVE_HEAD((head), \ field); \ _qsz--; \ } \ STAILQ_INSERT_TAIL(&_lb, _e, field); \ } \ } \ (head)->stqh_first = _lb.stqh_first; \ (head)->stqh_last = _lb.stqh_last; \ _sz *= 2; \ } while (_nmerges > 1); \ } while (/*CONSTCOND*/0) #endif #ifndef TAILQ_FOREACH_SAFE #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #endif /* ]] --QUEUE-MACROS-- */ /* * VCS Ids. */ #ifndef ELFTC_VCSID #if defined(__DragonFly__) #define ELFTC_VCSID(ID) __RCSID(ID) #endif #if defined(__FreeBSD__) #define ELFTC_VCSID(ID) __FBSDID(ID) #endif -#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) +#if defined(__APPLE__) || defined(__GLIBC__) || defined(__GNU__) || \ + defined(__linux__) #if defined(__GNUC__) #define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"") #else #define ELFTC_VCSID(ID) /**/ #endif #endif #if defined(__minix) #if defined(__GNUC__) #define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"") #else #define ELFTC_VCSID(ID) /**/ #endif /* __GNU__ */ #endif #if defined(__NetBSD__) #define ELFTC_VCSID(ID) __RCSID(ID) #endif #if defined(__OpenBSD__) #if defined(__GNUC__) #define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"") #else #define ELFTC_VCSID(ID) /**/ #endif /* __GNUC__ */ #endif #endif /* ELFTC_VCSID */ /* * Provide an equivalent for getprogname(3). */ #ifndef ELFTC_GETPROGNAME -#if defined(__DragonFly__) || defined(__FreeBSD__) || defined(__minix) || \ - defined(__NetBSD__) +#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || \ + defined(__minix) || defined(__NetBSD__) #include #define ELFTC_GETPROGNAME() getprogname() #endif /* __DragonFly__ || __FreeBSD__ || __minix || __NetBSD__ */ -#if defined(__GLIBC__) +#if defined(__GLIBC__) || defined(__linux__) /* * GLIBC based systems have a global 'char *' pointer referencing * the executable's name. */ extern const char *program_invocation_short_name; #define ELFTC_GETPROGNAME() program_invocation_short_name -#endif /* __GLIBC__ */ +#endif /* __GLIBC__ || __linux__ */ #if defined(__OpenBSD__) extern const char *__progname; #define ELFTC_GETPROGNAME() __progname #endif /* __OpenBSD__ */ #endif /* ELFTC_GETPROGNAME */ /** ** Per-OS configuration. **/ +#if defined(__APPLE__) + +#include +#define roundup2 roundup + +#define ELFTC_BYTE_ORDER _BYTE_ORDER +#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN +#define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN + +#define ELFTC_HAVE_MMAP 1 +#define ELFTC_HAVE_STRMODE 1 + +#endif /* __APPLE__ */ + + #if defined(__DragonFly__) #include #include #define ELFTC_BYTE_ORDER _BYTE_ORDER #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN #define ELFTC_HAVE_MMAP 1 #endif -#if defined(__GLIBC__) +#if defined(__GLIBC__) || defined(__linux__) #include #define ELFTC_BYTE_ORDER __BYTE_ORDER #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN __LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN __BIG_ENDIAN #define ELFTC_HAVE_MMAP 1 /* * Debian GNU/Linux and Debian GNU/kFreeBSD do not have strmode(3). */ #define ELFTC_HAVE_STRMODE 0 /* Whether we need to supply {be,le}32dec. */ #define ELFTC_NEED_BYTEORDER_EXTENSIONS 1 #define roundup2 roundup -#endif /* __GLIBC__ */ +#endif /* __GLIBC__ || __linux__ */ #if defined(__FreeBSD__) #include #include #define ELFTC_BYTE_ORDER _BYTE_ORDER #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 #if __FreeBSD_version <= 900000 #define ELFTC_BROKEN_YY_NO_INPUT 1 #endif #endif /* __FreeBSD__ */ #if defined(__minix) #define ELFTC_HAVE_MMAP 0 #endif /* __minix */ #if defined(__NetBSD__) #include #include #define ELFTC_BYTE_ORDER _BYTE_ORDER #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 #if __NetBSD_Version__ <= 599002100 /* from src/doc/CHANGES: flex(1): Import flex-2.5.35 [christos 20091025] */ /* and 5.99.21 was from Wed Oct 21 21:28:36 2009 UTC */ # define ELFTC_BROKEN_YY_NO_INPUT 1 #endif #endif /* __NetBSD __ */ #if defined(__OpenBSD__) #include #include #define ELFTC_BYTE_ORDER _BYTE_ORDER #define ELFTC_BYTE_ORDER_LITTLE_ENDIAN _LITTLE_ENDIAN #define ELFTC_BYTE_ORDER_BIG_ENDIAN _BIG_ENDIAN #define ELFTC_HAVE_MMAP 1 #define ELFTC_HAVE_STRMODE 1 #define ELFTC_NEED_BYTEORDER_EXTENSIONS 1 #define roundup2 roundup #endif /* __OpenBSD__ */ #endif /* _ELFTC_H */ Index: head/contrib/elftoolchain/common/elfdefinitions.h =================================================================== --- head/contrib/elftoolchain/common/elfdefinitions.h (revision 280931) +++ head/contrib/elftoolchain/common/elfdefinitions.h (revision 280932) @@ -1,2630 +1,2630 @@ /*- * Copyright (c) 2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfdefinitions.h 3149 2015-02-15 19:00:06Z emaste $ + * $Id: elfdefinitions.h 3178 2015-03-30 18:29:13Z emaste $ */ /* * These definitions are based on: * - The public specification of the ELF format as defined in the * October 2009 draft of System V ABI. * See: http://www.sco.com/developers/gabi/latest/ch4.intro.html * - The May 1998 (version 1.5) draft of "The ELF-64 object format". * - Processor-specific ELF ABI definitions for sparc, i386, amd64, mips, * ia64, and powerpc processors. * - The "Linkers and Libraries Guide", from Sun Microsystems. */ #ifndef _ELFDEFINITIONS_H_ #define _ELFDEFINITIONS_H_ #include /* * Types of capabilities. */ #define _ELF_DEFINE_CAPABILITIES() \ _ELF_DEFINE_CA(CA_SUNW_NULL, 0, "ignored") \ _ELF_DEFINE_CA(CA_SUNW_HW_1, 1, "hardware capability") \ _ELF_DEFINE_CA(CA_SUNW_SW_1, 2, "software capability") #undef _ELF_DEFINE_CA #define _ELF_DEFINE_CA(N, V, DESCR) N = V , enum { _ELF_DEFINE_CAPABILITIES() CA__LAST__ }; /* * Flags used with dynamic linking entries. */ #define _ELF_DEFINE_DYN_FLAGS() \ _ELF_DEFINE_DF(DF_ORIGIN, 0x1, \ "object being loaded may refer to $ORIGIN") \ _ELF_DEFINE_DF(DF_SYMBOLIC, 0x2, \ "search library for references before executable") \ _ELF_DEFINE_DF(DF_TEXTREL, 0x4, \ "relocation entries may modify text segment") \ _ELF_DEFINE_DF(DF_BIND_NOW, 0x8, \ "process relocation entries at load time") \ _ELF_DEFINE_DF(DF_STATIC_TLS, 0x10, \ "uses static thread-local storage") #undef _ELF_DEFINE_DF #define _ELF_DEFINE_DF(N, V, DESCR) N = V , enum { _ELF_DEFINE_DYN_FLAGS() DF__LAST__ }; /* * Dynamic linking entry types. */ #define _ELF_DEFINE_DYN_TYPES() \ _ELF_DEFINE_DT(DT_NULL, 0, "end of array") \ _ELF_DEFINE_DT(DT_NEEDED, 1, "names a needed library") \ _ELF_DEFINE_DT(DT_PLTRELSZ, 2, \ "size in bytes of associated relocation entries") \ _ELF_DEFINE_DT(DT_PLTGOT, 3, \ "address associated with the procedure linkage table") \ _ELF_DEFINE_DT(DT_HASH, 4, \ "address of the symbol hash table") \ _ELF_DEFINE_DT(DT_STRTAB, 5, \ "address of the string table") \ _ELF_DEFINE_DT(DT_SYMTAB, 6, \ "address of the symbol table") \ _ELF_DEFINE_DT(DT_RELA, 7, \ "address of the relocation table") \ _ELF_DEFINE_DT(DT_RELASZ, 8, "size of the DT_RELA table") \ _ELF_DEFINE_DT(DT_RELAENT, 9, "size of each DT_RELA entry") \ _ELF_DEFINE_DT(DT_STRSZ, 10, "size of the string table") \ _ELF_DEFINE_DT(DT_SYMENT, 11, \ "size of a symbol table entry") \ _ELF_DEFINE_DT(DT_INIT, 12, \ "address of the initialization function") \ _ELF_DEFINE_DT(DT_FINI, 13, \ "address of the finalization function") \ _ELF_DEFINE_DT(DT_SONAME, 14, "names the shared object") \ _ELF_DEFINE_DT(DT_RPATH, 15, \ "runtime library search path") \ _ELF_DEFINE_DT(DT_SYMBOLIC, 16, \ "alter symbol resolution algorithm") \ _ELF_DEFINE_DT(DT_REL, 17, \ "address of the DT_REL table") \ _ELF_DEFINE_DT(DT_RELSZ, 18, "size of the DT_REL table") \ _ELF_DEFINE_DT(DT_RELENT, 19, "size of each DT_REL entry") \ _ELF_DEFINE_DT(DT_PLTREL, 20, \ "type of relocation entry in the procedure linkage table") \ _ELF_DEFINE_DT(DT_DEBUG, 21, "used for debugging") \ _ELF_DEFINE_DT(DT_TEXTREL, 22, \ "text segment may be written to during relocation") \ _ELF_DEFINE_DT(DT_JMPREL, 23, \ "address of relocation entries associated with the procedure linkage table") \ _ELF_DEFINE_DT(DT_BIND_NOW, 24, \ "bind symbols at loading time") \ _ELF_DEFINE_DT(DT_INIT_ARRAY, 25, \ "pointers to initialization functions") \ _ELF_DEFINE_DT(DT_FINI_ARRAY, 26, \ "pointers to termination functions") \ _ELF_DEFINE_DT(DT_INIT_ARRAYSZ, 27, "size of the DT_INIT_ARRAY") \ _ELF_DEFINE_DT(DT_FINI_ARRAYSZ, 28, "size of the DT_FINI_ARRAY") \ _ELF_DEFINE_DT(DT_RUNPATH, 29, \ "index of library search path string") \ _ELF_DEFINE_DT(DT_FLAGS, 30, \ "flags specific to the object being loaded") \ _ELF_DEFINE_DT(DT_ENCODING, 32, "standard semantics") \ _ELF_DEFINE_DT(DT_PREINIT_ARRAY, 32, \ "pointers to pre-initialization functions") \ _ELF_DEFINE_DT(DT_PREINIT_ARRAYSZ, 33, \ "size of pre-initialization array") \ _ELF_DEFINE_DT(DT_MAXPOSTAGS, 34, \ "the number of positive tags") \ _ELF_DEFINE_DT(DT_LOOS, 0x6000000DUL, \ "start of OS-specific types") \ _ELF_DEFINE_DT(DT_SUNW_AUXILIARY, 0x6000000DUL, \ "offset of string naming auxiliary filtees") \ _ELF_DEFINE_DT(DT_SUNW_RTLDINF, 0x6000000EUL, "rtld internal use") \ _ELF_DEFINE_DT(DT_SUNW_FILTER, 0x6000000FUL, \ "offset of string naming standard filtees") \ _ELF_DEFINE_DT(DT_SUNW_CAP, 0x60000010UL, \ "address of hardware capabilities section") \ _ELF_DEFINE_DT(DT_HIOS, 0x6FFFF000UL, \ "end of OS-specific types") \ _ELF_DEFINE_DT(DT_VALRNGLO, 0x6FFFFD00UL, \ "start of range using the d_val field") \ _ELF_DEFINE_DT(DT_GNU_PRELINKED, 0x6FFFFDF5UL, \ "prelinking timestamp") \ _ELF_DEFINE_DT(DT_GNU_CONFLICTSZ, 0x6FFFFDF6UL, \ "size of conflict section") \ _ELF_DEFINE_DT(DT_GNU_LIBLISTSZ, 0x6FFFFDF7UL, \ "size of library list") \ _ELF_DEFINE_DT(DT_CHECKSUM, 0x6FFFFDF8UL, \ "checksum for the object") \ _ELF_DEFINE_DT(DT_PLTPADSZ, 0x6FFFFDF9UL, \ "size of PLT padding") \ _ELF_DEFINE_DT(DT_MOVEENT, 0x6FFFFDFAUL, \ "size of DT_MOVETAB entries") \ _ELF_DEFINE_DT(DT_MOVESZ, 0x6FFFFDFBUL, \ "total size of the MOVETAB table") \ -_ELF_DEFINE_DT(DT_FEATURE_1, 0x6FFFFDFCUL, "feature values") \ +_ELF_DEFINE_DT(DT_FEATURE, 0x6FFFFDFCUL, "feature values") \ _ELF_DEFINE_DT(DT_POSFLAG_1, 0x6FFFFDFDUL, \ "dynamic position flags") \ _ELF_DEFINE_DT(DT_SYMINSZ, 0x6FFFFDFEUL, \ "size of the DT_SYMINFO table") \ _ELF_DEFINE_DT(DT_SYMINENT, 0x6FFFFDFFUL, \ "size of a DT_SYMINFO entry") \ _ELF_DEFINE_DT(DT_VALRNGHI, 0x6FFFFDFFUL, \ "end of range using the d_val field") \ _ELF_DEFINE_DT(DT_ADDRRNGLO, 0x6FFFFE00UL, \ "start of range using the d_ptr field") \ _ELF_DEFINE_DT(DT_GNU_HASH, 0x6FFFFEF5UL, \ "GNU style hash tables") \ _ELF_DEFINE_DT(DT_GNU_CONFLICT, 0x6FFFFEF8UL, \ "address of conflict section") \ _ELF_DEFINE_DT(DT_GNU_LIBLIST, 0x6FFFFEF9UL, \ "address of conflict section") \ _ELF_DEFINE_DT(DT_CONFIG, 0x6FFFFEFAUL, \ "configuration file") \ _ELF_DEFINE_DT(DT_DEPAUDIT, 0x6FFFFEFBUL, \ "string defining audit libraries") \ _ELF_DEFINE_DT(DT_AUDIT, 0x6FFFFEFCUL, \ "string defining audit libraries") \ _ELF_DEFINE_DT(DT_PLTPAD, 0x6FFFFEFDUL, "PLT padding") \ _ELF_DEFINE_DT(DT_MOVETAB, 0x6FFFFEFEUL, \ "address of a move table") \ _ELF_DEFINE_DT(DT_SYMINFO, 0x6FFFFEFFUL, \ "address of the symbol information table") \ _ELF_DEFINE_DT(DT_ADDRRNGHI, 0x6FFFFEFFUL, \ "end of range using the d_ptr field") \ _ELF_DEFINE_DT(DT_VERSYM, 0x6FFFFFF0UL, \ "address of the version section") \ _ELF_DEFINE_DT(DT_RELACOUNT, 0x6FFFFFF9UL, \ "count of RELA relocations") \ _ELF_DEFINE_DT(DT_RELCOUNT, 0x6FFFFFFAUL, \ "count of REL relocations") \ _ELF_DEFINE_DT(DT_FLAGS_1, 0x6FFFFFFBUL, "flag values") \ _ELF_DEFINE_DT(DT_VERDEF, 0x6FFFFFFCUL, \ "address of the version definition segment") \ _ELF_DEFINE_DT(DT_VERDEFNUM, 0x6FFFFFFDUL, \ "the number of version definition entries") \ _ELF_DEFINE_DT(DT_VERNEED, 0x6FFFFFFEUL, \ "address of section with needed versions") \ _ELF_DEFINE_DT(DT_VERNEEDNUM, 0x6FFFFFFFUL, \ "the number of version needed entries") \ _ELF_DEFINE_DT(DT_LOPROC, 0x70000000UL, \ "start of processor-specific types") \ _ELF_DEFINE_DT(DT_ARM_SYMTABSZ, 0x70000001UL, \ "number of entries in the dynamic symbol table") \ _ELF_DEFINE_DT(DT_SPARC_REGISTER, 0x70000001UL, \ "index of an STT_SPARC_REGISTER symbol") \ _ELF_DEFINE_DT(DT_ARM_PREEMPTMAP, 0x70000002UL, \ "address of the preemption map") \ _ELF_DEFINE_DT(DT_MIPS_RLD_VERSION, 0x70000001UL, \ "version ID for runtime linker interface") \ _ELF_DEFINE_DT(DT_MIPS_TIME_STAMP, 0x70000002UL, \ "timestamp") \ _ELF_DEFINE_DT(DT_MIPS_ICHECKSUM, 0x70000003UL, \ "checksum of all external strings and common sizes") \ _ELF_DEFINE_DT(DT_MIPS_IVERSION, 0x70000004UL, \ "string table index of a version string") \ _ELF_DEFINE_DT(DT_MIPS_FLAGS, 0x70000005UL, \ "MIPS-specific flags") \ _ELF_DEFINE_DT(DT_MIPS_BASE_ADDRESS, 0x70000006UL, \ "base address for the executable/DSO") \ _ELF_DEFINE_DT(DT_MIPS_CONFLICT, 0x70000008UL, \ "address of .conflict section") \ _ELF_DEFINE_DT(DT_MIPS_LIBLIST, 0x70000009UL, \ "address of .liblist section") \ _ELF_DEFINE_DT(DT_MIPS_LOCAL_GOTNO, 0x7000000AUL, \ "number of local GOT entries") \ _ELF_DEFINE_DT(DT_MIPS_CONFLICTNO, 0x7000000BUL, \ "number of entries in the .conflict section") \ _ELF_DEFINE_DT(DT_MIPS_LIBLISTNO, 0x70000010UL, \ "number of entries in the .liblist section") \ _ELF_DEFINE_DT(DT_MIPS_SYMTABNO, 0x70000011UL, \ "number of entries in the .dynsym section") \ _ELF_DEFINE_DT(DT_MIPS_UNREFEXTNO, 0x70000012UL, \ "index of first external dynamic symbol not ref'ed locally") \ _ELF_DEFINE_DT(DT_MIPS_GOTSYM, 0x70000013UL, \ "index of first dynamic symbol corresponds to a GOT entry") \ _ELF_DEFINE_DT(DT_MIPS_HIPAGENO, 0x70000014UL, \ "number of page table entries in GOT") \ _ELF_DEFINE_DT(DT_MIPS_RLD_MAP, 0x70000016UL, \ "address of runtime linker map") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_CLASS, 0x70000017UL, \ "Delta C++ class definition") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_CLASS_NO, 0x70000018UL, \ "number of entries in DT_MIPS_DELTA_CLASS") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_INSTANCE, 0x70000019UL, \ "Delta C++ class instances") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_INSTANCE_NO, 0x7000001AUL, \ "number of entries in DT_MIPS_DELTA_INSTANCE") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_RELOC, 0x7000001BUL, \ "Delta relocations") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_RELOC_NO, 0x7000001CUL, \ "number of entries in DT_MIPS_DELTA_RELOC") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_SYM, 0x7000001DUL, \ "Delta symbols refered by Delta relocations") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_SYM_NO, 0x7000001EUL, \ "number of entries in DT_MIPS_DELTA_SYM") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_CLASSSYM, 0x70000020UL, \ "Delta symbols for class declarations") \ _ELF_DEFINE_DT(DT_MIPS_DELTA_CLASSSYM_NO, 0x70000021UL, \ "number of entries in DT_MIPS_DELTA_CLASSSYM") \ _ELF_DEFINE_DT(DT_MIPS_CXX_FLAGS, 0x70000022UL, \ "C++ flavor flags") \ _ELF_DEFINE_DT(DT_MIPS_PIXIE_INIT, 0x70000023UL, \ "address of an initialization routine created by pixie") \ _ELF_DEFINE_DT(DT_MIPS_SYMBOL_LIB, 0x70000024UL, \ "address of .MIPS.symlib section") \ _ELF_DEFINE_DT(DT_MIPS_LOCALPAGE_GOTIDX, 0x70000025UL, \ "GOT index of first page table entry for a segment") \ _ELF_DEFINE_DT(DT_MIPS_LOCAL_GOTIDX, 0x70000026UL, \ "GOT index of first page table entry for a local symbol") \ _ELF_DEFINE_DT(DT_MIPS_HIDDEN_GOTIDX, 0x70000027UL, \ "GOT index of first page table entry for a hidden symbol") \ _ELF_DEFINE_DT(DT_MIPS_PROTECTED_GOTIDX, 0x70000028UL, \ "GOT index of first page table entry for a protected symbol") \ _ELF_DEFINE_DT(DT_MIPS_OPTIONS, 0x70000029UL, \ "address of .MIPS.options section") \ _ELF_DEFINE_DT(DT_MIPS_INTERFACE, 0x7000002AUL, \ "address of .MIPS.interface section") \ _ELF_DEFINE_DT(DT_MIPS_DYNSTR_ALIGN, 0x7000002BUL, "???") \ _ELF_DEFINE_DT(DT_MIPS_INTERFACE_SIZE, 0x7000002CUL, \ "size of .MIPS.interface section") \ _ELF_DEFINE_DT(DT_MIPS_RLD_TEXT_RESOLVE_ADDR, 0x7000002DUL, \ "address of _rld_text_resolve in GOT") \ _ELF_DEFINE_DT(DT_MIPS_PERF_SUFFIX, 0x7000002EUL, \ "default suffix of DSO to be appended by dlopen") \ _ELF_DEFINE_DT(DT_MIPS_COMPACT_SIZE, 0x7000002FUL, \ "size of a ucode compact relocation record (o32)") \ _ELF_DEFINE_DT(DT_MIPS_GP_VALUE, 0x70000030UL, \ "GP value of a specified GP relative range") \ _ELF_DEFINE_DT(DT_MIPS_AUX_DYNAMIC, 0x70000031UL, \ "address of an auxiliary dynamic table") \ _ELF_DEFINE_DT(DT_MIPS_PLTGOT, 0x70000032UL, \ "address of the PLTGOT") \ _ELF_DEFINE_DT(DT_MIPS_RLD_OBJ_UPDATE, 0x70000033UL, \ "object list update callback") \ _ELF_DEFINE_DT(DT_MIPS_RWPLT, 0x70000034UL, \ "address of a writable PLT") \ _ELF_DEFINE_DT(DT_PPC_GOT, 0x70000000UL, \ "value of _GLOBAL_OFFSET_TABLE_") \ _ELF_DEFINE_DT(DT_PPC_TLSOPT, 0x70000001UL, \ "TLS descriptor should be optimized") \ _ELF_DEFINE_DT(DT_PPC64_GLINK, 0x70000000UL, \ "address of .glink section") \ _ELF_DEFINE_DT(DT_PPC64_OPD, 0x70000001UL, \ "address of .opd section") \ _ELF_DEFINE_DT(DT_PPC64_OPDSZ, 0x70000002UL, \ "size of .opd section") \ _ELF_DEFINE_DT(DT_PPC64_TLSOPT, 0x70000003UL, \ "TLS descriptor should be optimized") \ _ELF_DEFINE_DT(DT_AUXILIARY, 0x7FFFFFFDUL, \ "offset of string naming auxiliary filtees") \ _ELF_DEFINE_DT(DT_USED, 0x7FFFFFFEUL, "ignored") \ _ELF_DEFINE_DT(DT_FILTER, 0x7FFFFFFFUL, \ "index of string naming filtees") \ _ELF_DEFINE_DT(DT_HIPROC, 0x7FFFFFFFUL, \ "end of processor-specific types") #undef _ELF_DEFINE_DT #define _ELF_DEFINE_DT(N, V, DESCR) N = V , enum { _ELF_DEFINE_DYN_TYPES() DT__LAST__ = DT_HIPROC }; #define DT_DEPRECATED_SPARC_REGISTER DT_SPARC_REGISTER /* * Flags used in the executable header (field: e_flags). */ #define _ELF_DEFINE_EHDR_FLAGS() \ _ELF_DEFINE_EF(EF_ARM_RELEXEC, 0x00000001UL, \ "dynamic segment describes only how to relocate segments") \ _ELF_DEFINE_EF(EF_ARM_HASENTRY, 0x00000002UL, \ "e_entry contains a program entry point") \ _ELF_DEFINE_EF(EF_ARM_SYMSARESORTED, 0x00000004UL, \ "subsection of symbol table is sorted by symbol value") \ _ELF_DEFINE_EF(EF_ARM_DYNSYMSUSESEGIDX, 0x00000008UL, \ "dynamic symbol st_shndx = containing segment index + 1") \ _ELF_DEFINE_EF(EF_ARM_MAPSYMSFIRST, 0x00000010UL, \ "mapping symbols precede other local symbols in symtab") \ _ELF_DEFINE_EF(EF_ARM_BE8, 0x00800000UL, \ "file contains BE-8 code") \ _ELF_DEFINE_EF(EF_ARM_LE8, 0x00400000UL, \ "file contains LE-8 code") \ _ELF_DEFINE_EF(EF_ARM_EABIMASK, 0xFF000000UL, \ "mask for ARM EABI version number (0 denotes GNU or unknown)") \ _ELF_DEFINE_EF(EF_ARM_EABI_UNKNOWN, 0x00000000UL, \ "Unknown or GNU ARM EABI version number") \ _ELF_DEFINE_EF(EF_ARM_EABI_VER1, 0x01000000UL, \ "ARM EABI version 1") \ _ELF_DEFINE_EF(EF_ARM_EABI_VER2, 0x02000000UL, \ "ARM EABI version 2") \ _ELF_DEFINE_EF(EF_ARM_EABI_VER3, 0x03000000UL, \ "ARM EABI version 3") \ _ELF_DEFINE_EF(EF_ARM_EABI_VER4, 0x04000000UL, \ "ARM EABI version 4") \ _ELF_DEFINE_EF(EF_ARM_EABI_VER5, 0x05000000UL, \ "ARM EABI version 5") \ _ELF_DEFINE_EF(EF_ARM_INTERWORK, 0x00000004UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_APCS_26, 0x00000008UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_APCS_FLOAT, 0x00000010UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_PIC, 0x00000020UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_ALIGN8, 0x00000040UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_NEW_ABI, 0x00000080UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_OLD_ABI, 0x00000100UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_SOFT_FLOAT, 0x00000200UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_VFP_FLOAT, 0x00000400UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_ARM_MAVERICK_FLOAT, 0x00000800UL, \ "GNU EABI extension") \ _ELF_DEFINE_EF(EF_MIPS_NOREORDER, 0x00000001UL, \ "at least one .noreorder directive appeared in the source") \ _ELF_DEFINE_EF(EF_MIPS_PIC, 0x00000002UL, \ "file contains position independent code") \ _ELF_DEFINE_EF(EF_MIPS_CPIC, 0x00000004UL, \ "file's code uses standard conventions for calling PIC") \ _ELF_DEFINE_EF(EF_MIPS_UCODE, 0x00000010UL, \ "file contains UCODE (obsolete)") \ _ELF_DEFINE_EF(EF_MIPS_ABI2, 0x00000020UL, \ "file follows MIPS III 32-bit ABI") \ _ELF_DEFINE_EF(EF_MIPS_OPTIONS_FIRST, 0x00000080UL, \ "ld(1) should process .MIPS.options section first") \ _ELF_DEFINE_EF(EF_MIPS_ARCH_ASE, 0x0F000000UL, \ "file uses application-specific architectural extensions") \ _ELF_DEFINE_EF(EF_MIPS_ARCH_ASE_MDMX, 0x08000000UL, \ "file uses MDMX multimedia extensions") \ _ELF_DEFINE_EF(EF_MIPS_ARCH_ASE_M16, 0x04000000UL, \ "file uses MIPS-16 ISA extensions") \ _ELF_DEFINE_EF(EF_MIPS_ARCH, 0xF0000000UL, \ "4-bit MIPS architecture field") \ _ELF_DEFINE_EF(EF_PPC_EMB, 0x80000000UL, \ "Embedded PowerPC flag") \ _ELF_DEFINE_EF(EF_PPC_RELOCATABLE, 0x00010000UL, \ "-mrelocatable flag") \ _ELF_DEFINE_EF(EF_PPC_RELOCATABLE_LIB, 0x00008000UL, \ "-mrelocatable-lib flag") \ _ELF_DEFINE_EF(EF_SPARC_EXT_MASK, 0x00ffff00UL, \ "Vendor Extension mask") \ _ELF_DEFINE_EF(EF_SPARC_32PLUS, 0x00000100UL, \ "Generic V8+ features") \ _ELF_DEFINE_EF(EF_SPARC_SUN_US1, 0x00000200UL, \ "Sun UltraSPARCTM 1 Extensions") \ _ELF_DEFINE_EF(EF_SPARC_HAL_R1, 0x00000400UL, "HAL R1 Extensions") \ _ELF_DEFINE_EF(EF_SPARC_SUN_US3, 0x00000800UL, \ "Sun UltraSPARC 3 Extensions") \ _ELF_DEFINE_EF(EF_SPARCV9_MM, 0x00000003UL, \ "Mask for Memory Model") \ _ELF_DEFINE_EF(EF_SPARCV9_TSO, 0x00000000UL, \ "Total Store Ordering") \ _ELF_DEFINE_EF(EF_SPARCV9_PSO, 0x00000001UL, \ "Partial Store Ordering") \ _ELF_DEFINE_EF(EF_SPARCV9_RMO, 0x00000002UL, \ "Relaxed Memory Ordering") #undef _ELF_DEFINE_EF #define _ELF_DEFINE_EF(N, V, DESCR) N = V , enum { _ELF_DEFINE_EHDR_FLAGS() EF__LAST__ }; /* * Offsets in the `ei_ident[]` field of an ELF executable header. */ #define _ELF_DEFINE_EI_OFFSETS() \ _ELF_DEFINE_EI(EI_MAG0, 0, "magic number") \ _ELF_DEFINE_EI(EI_MAG1, 1, "magic number") \ _ELF_DEFINE_EI(EI_MAG2, 2, "magic number") \ _ELF_DEFINE_EI(EI_MAG3, 3, "magic number") \ _ELF_DEFINE_EI(EI_CLASS, 4, "file class") \ _ELF_DEFINE_EI(EI_DATA, 5, "data encoding") \ _ELF_DEFINE_EI(EI_VERSION, 6, "file version") \ _ELF_DEFINE_EI(EI_OSABI, 7, "OS ABI kind") \ _ELF_DEFINE_EI(EI_ABIVERSION, 8, "OS ABI version") \ _ELF_DEFINE_EI(EI_PAD, 9, "padding start") \ _ELF_DEFINE_EI(EI_NIDENT, 16, "total size") #undef _ELF_DEFINE_EI #define _ELF_DEFINE_EI(N, V, DESCR) N = V , enum { _ELF_DEFINE_EI_OFFSETS() EI__LAST__ }; /* * The ELF class of an object. */ #define _ELF_DEFINE_ELFCLASS() \ _ELF_DEFINE_EC(ELFCLASSNONE, 0, "Unknown ELF class") \ _ELF_DEFINE_EC(ELFCLASS32, 1, "32 bit objects") \ _ELF_DEFINE_EC(ELFCLASS64, 2, "64 bit objects") #undef _ELF_DEFINE_EC #define _ELF_DEFINE_EC(N, V, DESCR) N = V , enum { _ELF_DEFINE_ELFCLASS() EC__LAST__ }; /* * Endianness of data in an ELF object. */ #define _ELF_DEFINE_ELF_DATA_ENDIANNESS() \ _ELF_DEFINE_ED(ELFDATANONE, 0, "Unknown data endianness") \ _ELF_DEFINE_ED(ELFDATA2LSB, 1, "little endian") \ _ELF_DEFINE_ED(ELFDATA2MSB, 2, "big endian") #undef _ELF_DEFINE_ED #define _ELF_DEFINE_ED(N, V, DESCR) N = V , enum { _ELF_DEFINE_ELF_DATA_ENDIANNESS() ED__LAST__ }; /* * Values of the magic numbers used in identification array. */ #define _ELF_DEFINE_ELF_MAGIC() \ _ELF_DEFINE_EMAG(ELFMAG0, 0x7FU) \ _ELF_DEFINE_EMAG(ELFMAG1, 'E') \ _ELF_DEFINE_EMAG(ELFMAG2, 'L') \ _ELF_DEFINE_EMAG(ELFMAG3, 'F') #undef _ELF_DEFINE_EMAG #define _ELF_DEFINE_EMAG(N, V) N = V , enum { _ELF_DEFINE_ELF_MAGIC() ELFMAG__LAST__ }; /* * ELF OS ABI field. */ #define _ELF_DEFINE_ELF_OSABI() \ _ELF_DEFINE_EABI(ELFOSABI_NONE, 0, \ "No extensions or unspecified") \ _ELF_DEFINE_EABI(ELFOSABI_SYSV, 0, "SYSV") \ _ELF_DEFINE_EABI(ELFOSABI_HPUX, 1, "Hewlett-Packard HP-UX") \ _ELF_DEFINE_EABI(ELFOSABI_NETBSD, 2, "NetBSD") \ _ELF_DEFINE_EABI(ELFOSABI_GNU, 3, "GNU") \ _ELF_DEFINE_EABI(ELFOSABI_HURD, 4, "GNU/HURD") \ _ELF_DEFINE_EABI(ELFOSABI_86OPEN, 5, "86Open Common ABI") \ _ELF_DEFINE_EABI(ELFOSABI_SOLARIS, 6, "Sun Solaris") \ _ELF_DEFINE_EABI(ELFOSABI_AIX, 7, "AIX") \ _ELF_DEFINE_EABI(ELFOSABI_IRIX, 8, "IRIX") \ _ELF_DEFINE_EABI(ELFOSABI_FREEBSD, 9, "FreeBSD") \ _ELF_DEFINE_EABI(ELFOSABI_TRU64, 10, "Compaq TRU64 UNIX") \ _ELF_DEFINE_EABI(ELFOSABI_MODESTO, 11, "Novell Modesto") \ _ELF_DEFINE_EABI(ELFOSABI_OPENBSD, 12, "Open BSD") \ _ELF_DEFINE_EABI(ELFOSABI_OPENVMS, 13, "Open VMS") \ _ELF_DEFINE_EABI(ELFOSABI_NSK, 14, \ "Hewlett-Packard Non-Stop Kernel") \ _ELF_DEFINE_EABI(ELFOSABI_AROS, 15, "Amiga Research OS") \ _ELF_DEFINE_EABI(ELFOSABI_FENIXOS, 16, \ "The FenixOS highly scalable multi-core OS") \ _ELF_DEFINE_EABI(ELFOSABI_ARM_AEABI, 64, \ "ARM specific symbol versioning extensions") \ _ELF_DEFINE_EABI(ELFOSABI_ARM, 97, "ARM ABI") \ _ELF_DEFINE_EABI(ELFOSABI_STANDALONE, 255, \ "Standalone (embedded) application") #undef _ELF_DEFINE_EABI #define _ELF_DEFINE_EABI(N, V, DESCR) N = V , enum { _ELF_DEFINE_ELF_OSABI() ELFOSABI__LAST__ }; #define ELFOSABI_LINUX ELFOSABI_GNU /* * ELF Machine types: (EM_*). */ #define _ELF_DEFINE_ELF_MACHINES() \ _ELF_DEFINE_EM(EM_NONE, 0, "No machine") \ _ELF_DEFINE_EM(EM_M32, 1, "AT&T WE 32100") \ _ELF_DEFINE_EM(EM_SPARC, 2, "SPARC") \ _ELF_DEFINE_EM(EM_386, 3, "Intel 80386") \ _ELF_DEFINE_EM(EM_68K, 4, "Motorola 68000") \ _ELF_DEFINE_EM(EM_88K, 5, "Motorola 88000") \ _ELF_DEFINE_EM(EM_860, 7, "Intel 80860") \ _ELF_DEFINE_EM(EM_MIPS, 8, "MIPS I Architecture") \ _ELF_DEFINE_EM(EM_S370, 9, "IBM System/370 Processor") \ _ELF_DEFINE_EM(EM_MIPS_RS3_LE, 10, "MIPS RS3000 Little-endian") \ _ELF_DEFINE_EM(EM_PARISC, 15, "Hewlett-Packard PA-RISC") \ _ELF_DEFINE_EM(EM_VPP500, 17, "Fujitsu VPP500") \ _ELF_DEFINE_EM(EM_SPARC32PLUS, 18, \ "Enhanced instruction set SPARC") \ _ELF_DEFINE_EM(EM_960, 19, "Intel 80960") \ _ELF_DEFINE_EM(EM_PPC, 20, "PowerPC") \ _ELF_DEFINE_EM(EM_PPC64, 21, "64-bit PowerPC") \ _ELF_DEFINE_EM(EM_S390, 22, "IBM System/390 Processor") \ _ELF_DEFINE_EM(EM_SPU, 23, "IBM SPU/SPC") \ _ELF_DEFINE_EM(EM_V800, 36, "NEC V800") \ _ELF_DEFINE_EM(EM_FR20, 37, "Fujitsu FR20") \ _ELF_DEFINE_EM(EM_RH32, 38, "TRW RH-32") \ _ELF_DEFINE_EM(EM_RCE, 39, "Motorola RCE") \ _ELF_DEFINE_EM(EM_ARM, 40, "Advanced RISC Machines ARM") \ _ELF_DEFINE_EM(EM_ALPHA, 41, "Digital Alpha") \ _ELF_DEFINE_EM(EM_SH, 42, "Hitachi SH") \ _ELF_DEFINE_EM(EM_SPARCV9, 43, "SPARC Version 9") \ _ELF_DEFINE_EM(EM_TRICORE, 44, \ "Siemens TriCore embedded processor") \ _ELF_DEFINE_EM(EM_ARC, 45, \ "Argonaut RISC Core, Argonaut Technologies Inc.") \ _ELF_DEFINE_EM(EM_H8_300, 46, "Hitachi H8/300") \ _ELF_DEFINE_EM(EM_H8_300H, 47, "Hitachi H8/300H") \ _ELF_DEFINE_EM(EM_H8S, 48, "Hitachi H8S") \ _ELF_DEFINE_EM(EM_H8_500, 49, "Hitachi H8/500") \ _ELF_DEFINE_EM(EM_IA_64, 50, \ "Intel IA-64 processor architecture") \ _ELF_DEFINE_EM(EM_MIPS_X, 51, "Stanford MIPS-X") \ _ELF_DEFINE_EM(EM_COLDFIRE, 52, "Motorola ColdFire") \ _ELF_DEFINE_EM(EM_68HC12, 53, "Motorola M68HC12") \ _ELF_DEFINE_EM(EM_MMA, 54, \ "Fujitsu MMA Multimedia Accelerator") \ _ELF_DEFINE_EM(EM_PCP, 55, "Siemens PCP") \ _ELF_DEFINE_EM(EM_NCPU, 56, \ "Sony nCPU embedded RISC processor") \ _ELF_DEFINE_EM(EM_NDR1, 57, "Denso NDR1 microprocessor") \ _ELF_DEFINE_EM(EM_STARCORE, 58, "Motorola Star*Core processor") \ _ELF_DEFINE_EM(EM_ME16, 59, "Toyota ME16 processor") \ _ELF_DEFINE_EM(EM_ST100, 60, \ "STMicroelectronics ST100 processor") \ _ELF_DEFINE_EM(EM_TINYJ, 61, \ "Advanced Logic Corp. TinyJ embedded processor family") \ _ELF_DEFINE_EM(EM_X86_64, 62, "AMD x86-64 architecture") \ _ELF_DEFINE_EM(EM_PDSP, 63, "Sony DSP Processor") \ _ELF_DEFINE_EM(EM_PDP10, 64, \ "Digital Equipment Corp. PDP-10") \ _ELF_DEFINE_EM(EM_PDP11, 65, \ "Digital Equipment Corp. PDP-11") \ _ELF_DEFINE_EM(EM_FX66, 66, "Siemens FX66 microcontroller") \ _ELF_DEFINE_EM(EM_ST9PLUS, 67, \ "STMicroelectronics ST9+ 8/16 bit microcontroller") \ _ELF_DEFINE_EM(EM_ST7, 68, \ "STMicroelectronics ST7 8-bit microcontroller") \ _ELF_DEFINE_EM(EM_68HC16, 69, \ "Motorola MC68HC16 Microcontroller") \ _ELF_DEFINE_EM(EM_68HC11, 70, \ "Motorola MC68HC11 Microcontroller") \ _ELF_DEFINE_EM(EM_68HC08, 71, \ "Motorola MC68HC08 Microcontroller") \ _ELF_DEFINE_EM(EM_68HC05, 72, \ "Motorola MC68HC05 Microcontroller") \ _ELF_DEFINE_EM(EM_SVX, 73, "Silicon Graphics SVx") \ _ELF_DEFINE_EM(EM_ST19, 74, \ "STMicroelectronics ST19 8-bit microcontroller") \ _ELF_DEFINE_EM(EM_VAX, 75, "Digital VAX") \ _ELF_DEFINE_EM(EM_CRIS, 76, \ "Axis Communications 32-bit embedded processor") \ _ELF_DEFINE_EM(EM_JAVELIN, 77, \ "Infineon Technologies 32-bit embedded processor") \ _ELF_DEFINE_EM(EM_FIREPATH, 78, \ "Element 14 64-bit DSP Processor") \ _ELF_DEFINE_EM(EM_ZSP, 79, \ "LSI Logic 16-bit DSP Processor") \ _ELF_DEFINE_EM(EM_MMIX, 80, \ "Donald Knuth's educational 64-bit processor") \ _ELF_DEFINE_EM(EM_HUANY, 81, \ "Harvard University machine-independent object files") \ _ELF_DEFINE_EM(EM_PRISM, 82, "SiTera Prism") \ _ELF_DEFINE_EM(EM_AVR, 83, \ "Atmel AVR 8-bit microcontroller") \ _ELF_DEFINE_EM(EM_FR30, 84, "Fujitsu FR30") \ _ELF_DEFINE_EM(EM_D10V, 85, "Mitsubishi D10V") \ _ELF_DEFINE_EM(EM_D30V, 86, "Mitsubishi D30V") \ _ELF_DEFINE_EM(EM_V850, 87, "NEC v850") \ _ELF_DEFINE_EM(EM_M32R, 88, "Mitsubishi M32R") \ _ELF_DEFINE_EM(EM_MN10300, 89, "Matsushita MN10300") \ _ELF_DEFINE_EM(EM_MN10200, 90, "Matsushita MN10200") \ _ELF_DEFINE_EM(EM_PJ, 91, "picoJava") \ _ELF_DEFINE_EM(EM_OPENRISC, 92, \ "OpenRISC 32-bit embedded processor") \ _ELF_DEFINE_EM(EM_ARC_COMPACT, 93, \ "ARC International ARCompact processor") \ _ELF_DEFINE_EM(EM_XTENSA, 94, \ "Tensilica Xtensa Architecture") \ _ELF_DEFINE_EM(EM_VIDEOCORE, 95, \ "Alphamosaic VideoCore processor") \ _ELF_DEFINE_EM(EM_TMM_GPP, 96, \ "Thompson Multimedia General Purpose Processor") \ _ELF_DEFINE_EM(EM_NS32K, 97, \ "National Semiconductor 32000 series") \ _ELF_DEFINE_EM(EM_TPC, 98, "Tenor Network TPC processor") \ _ELF_DEFINE_EM(EM_SNP1K, 99, "Trebia SNP 1000 processor") \ _ELF_DEFINE_EM(EM_ST200, 100, \ "STMicroelectronics (www.st.com) ST200 microcontroller") \ _ELF_DEFINE_EM(EM_IP2K, 101, \ "Ubicom IP2xxx microcontroller family") \ _ELF_DEFINE_EM(EM_MAX, 102, "MAX Processor") \ _ELF_DEFINE_EM(EM_CR, 103, \ "National Semiconductor CompactRISC microprocessor") \ _ELF_DEFINE_EM(EM_F2MC16, 104, "Fujitsu F2MC16") \ _ELF_DEFINE_EM(EM_MSP430, 105, \ "Texas Instruments embedded microcontroller msp430") \ _ELF_DEFINE_EM(EM_BLACKFIN, 106, \ "Analog Devices Blackfin (DSP) processor") \ _ELF_DEFINE_EM(EM_SE_C33, 107, \ "S1C33 Family of Seiko Epson processors") \ _ELF_DEFINE_EM(EM_SEP, 108, \ "Sharp embedded microprocessor") \ _ELF_DEFINE_EM(EM_ARCA, 109, "Arca RISC Microprocessor") \ _ELF_DEFINE_EM(EM_UNICORE, 110, \ "Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University") \ _ELF_DEFINE_EM(EM_EXCESS, 111, \ "eXcess: 16/32/64-bit configurable embedded CPU") \ _ELF_DEFINE_EM(EM_DXP, 112, \ "Icera Semiconductor Inc. Deep Execution Processor") \ _ELF_DEFINE_EM(EM_ALTERA_NIOS2, 113, \ "Altera Nios II soft-core processor") \ _ELF_DEFINE_EM(EM_CRX, 114, \ "National Semiconductor CompactRISC CRX microprocessor") \ _ELF_DEFINE_EM(EM_XGATE, 115, \ "Motorola XGATE embedded processor") \ _ELF_DEFINE_EM(EM_C166, 116, \ "Infineon C16x/XC16x processor") \ _ELF_DEFINE_EM(EM_M16C, 117, \ "Renesas M16C series microprocessors") \ _ELF_DEFINE_EM(EM_DSPIC30F, 118, \ "Microchip Technology dsPIC30F Digital Signal Controller") \ _ELF_DEFINE_EM(EM_CE, 119, \ "Freescale Communication Engine RISC core") \ _ELF_DEFINE_EM(EM_M32C, 120, \ "Renesas M32C series microprocessors") \ _ELF_DEFINE_EM(EM_TSK3000, 131, "Altium TSK3000 core") \ _ELF_DEFINE_EM(EM_RS08, 132, \ "Freescale RS08 embedded processor") \ _ELF_DEFINE_EM(EM_SHARC, 133, \ "Analog Devices SHARC family of 32-bit DSP processors") \ _ELF_DEFINE_EM(EM_ECOG2, 134, \ "Cyan Technology eCOG2 microprocessor") \ _ELF_DEFINE_EM(EM_SCORE7, 135, \ "Sunplus S+core7 RISC processor") \ _ELF_DEFINE_EM(EM_DSP24, 136, \ "New Japan Radio (NJR) 24-bit DSP Processor") \ _ELF_DEFINE_EM(EM_VIDEOCORE3, 137, \ "Broadcom VideoCore III processor") \ _ELF_DEFINE_EM(EM_LATTICEMICO32, 138, \ "RISC processor for Lattice FPGA architecture") \ _ELF_DEFINE_EM(EM_SE_C17, 139, "Seiko Epson C17 family") \ _ELF_DEFINE_EM(EM_TI_C6000, 140, \ "The Texas Instruments TMS320C6000 DSP family") \ _ELF_DEFINE_EM(EM_TI_C2000, 141, \ "The Texas Instruments TMS320C2000 DSP family") \ _ELF_DEFINE_EM(EM_TI_C5500, 142, \ "The Texas Instruments TMS320C55x DSP family") \ _ELF_DEFINE_EM(EM_MMDSP_PLUS, 160, \ "STMicroelectronics 64bit VLIW Data Signal Processor") \ _ELF_DEFINE_EM(EM_CYPRESS_M8C, 161, "Cypress M8C microprocessor") \ _ELF_DEFINE_EM(EM_R32C, 162, \ "Renesas R32C series microprocessors") \ _ELF_DEFINE_EM(EM_TRIMEDIA, 163, \ "NXP Semiconductors TriMedia architecture family") \ _ELF_DEFINE_EM(EM_QDSP6, 164, "QUALCOMM DSP6 Processor") \ _ELF_DEFINE_EM(EM_8051, 165, "Intel 8051 and variants") \ _ELF_DEFINE_EM(EM_STXP7X, 166, \ "STMicroelectronics STxP7x family of configurable and extensible RISC processors") \ _ELF_DEFINE_EM(EM_NDS32, 167, \ "Andes Technology compact code size embedded RISC processor family") \ _ELF_DEFINE_EM(EM_ECOG1, 168, \ "Cyan Technology eCOG1X family") \ _ELF_DEFINE_EM(EM_ECOG1X, 168, \ "Cyan Technology eCOG1X family") \ _ELF_DEFINE_EM(EM_MAXQ30, 169, \ "Dallas Semiconductor MAXQ30 Core Micro-controllers") \ _ELF_DEFINE_EM(EM_XIMO16, 170, \ "New Japan Radio (NJR) 16-bit DSP Processor") \ _ELF_DEFINE_EM(EM_MANIK, 171, \ "M2000 Reconfigurable RISC Microprocessor") \ _ELF_DEFINE_EM(EM_CRAYNV2, 172, \ "Cray Inc. NV2 vector architecture") \ _ELF_DEFINE_EM(EM_RX, 173, "Renesas RX family") \ _ELF_DEFINE_EM(EM_METAG, 174, \ "Imagination Technologies META processor architecture") \ _ELF_DEFINE_EM(EM_MCST_ELBRUS, 175, \ "MCST Elbrus general purpose hardware architecture") \ _ELF_DEFINE_EM(EM_ECOG16, 176, \ "Cyan Technology eCOG16 family") \ _ELF_DEFINE_EM(EM_CR16, 177, \ "National Semiconductor CompactRISC CR16 16-bit microprocessor") \ _ELF_DEFINE_EM(EM_ETPU, 178, \ "Freescale Extended Time Processing Unit") \ _ELF_DEFINE_EM(EM_SLE9X, 179, \ "Infineon Technologies SLE9X core") \ _ELF_DEFINE_EM(EM_AARCH64, 183, \ "AArch64 (64-bit ARM)") \ _ELF_DEFINE_EM(EM_AVR32, 185, \ "Atmel Corporation 32-bit microprocessor family") \ _ELF_DEFINE_EM(EM_STM8, 186, \ "STMicroeletronics STM8 8-bit microcontroller") \ _ELF_DEFINE_EM(EM_TILE64, 187, \ "Tilera TILE64 multicore architecture family") \ _ELF_DEFINE_EM(EM_TILEPRO, 188, \ "Tilera TILEPro multicore architecture family") \ _ELF_DEFINE_EM(EM_MICROBLAZE, 189, \ "Xilinx MicroBlaze 32-bit RISC soft processor core") \ _ELF_DEFINE_EM(EM_CUDA, 190, "NVIDIA CUDA architecture") \ _ELF_DEFINE_EM(EM_TILEGX, 191, \ "Tilera TILE-Gx multicore architecture family") \ _ELF_DEFINE_EM(EM_CLOUDSHIELD, 192, \ "CloudShield architecture family") \ _ELF_DEFINE_EM(EM_COREA_1ST, 193, \ "KIPO-KAIST Core-A 1st generation processor family") \ _ELF_DEFINE_EM(EM_COREA_2ND, 194, \ "KIPO-KAIST Core-A 2nd generation processor family") \ _ELF_DEFINE_EM(EM_ARC_COMPACT2, 195, "Synopsys ARCompact V2") \ _ELF_DEFINE_EM(EM_OPEN8, 196, \ "Open8 8-bit RISC soft processor core") \ _ELF_DEFINE_EM(EM_RL78, 197, "Renesas RL78 family") \ _ELF_DEFINE_EM(EM_VIDEOCORE5, 198, "Broadcom VideoCore V processor") \ _ELF_DEFINE_EM(EM_78KOR, 199, "Renesas 78KOR family") \ _ELF_DEFINE_EM(EM_56800EX, 200, \ "Freescale 56800EX Digital Signal Controller") \ _ELF_DEFINE_EM(EM_BA1, 201, "Beyond BA1 CPU architecture") \ _ELF_DEFINE_EM(EM_BA2, 202, "Beyond BA2 CPU architecture") \ _ELF_DEFINE_EM(EM_XCORE, 203, "XMOS xCORE processor family") \ _ELF_DEFINE_EM(EM_MCHP_PIC, 204, "Microchip 8-bit PIC(r) family") \ _ELF_DEFINE_EM(EM_INTEL205, 205, "Reserved by Intel") \ _ELF_DEFINE_EM(EM_INTEL206, 206, "Reserved by Intel") \ _ELF_DEFINE_EM(EM_INTEL207, 207, "Reserved by Intel") \ _ELF_DEFINE_EM(EM_INTEL208, 208, "Reserved by Intel") \ _ELF_DEFINE_EM(EM_INTEL209, 209, "Reserved by Intel") \ _ELF_DEFINE_EM(EM_KM32, 210, "KM211 KM32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX32, 211, "KM211 KMX32 32-bit processor") \ _ELF_DEFINE_EM(EM_KMX16, 212, "KM211 KMX16 16-bit processor") \ _ELF_DEFINE_EM(EM_KMX8, 213, "KM211 KMX8 8-bit processor") \ _ELF_DEFINE_EM(EM_KVARC, 214, "KM211 KMX32 KVARC processor") #undef _ELF_DEFINE_EM #define _ELF_DEFINE_EM(N, V, DESCR) N = V , enum { _ELF_DEFINE_ELF_MACHINES() EM__LAST__ }; /* Other synonyms. */ #define EM_AMD64 EM_X86_64 #define EM_ARC_A5 EM_ARC_COMPACT /* * ELF file types: (ET_*). */ #define _ELF_DEFINE_ELF_TYPES() \ _ELF_DEFINE_ET(ET_NONE, 0, "No file type") \ _ELF_DEFINE_ET(ET_REL, 1, "Relocatable object") \ _ELF_DEFINE_ET(ET_EXEC, 2, "Executable") \ _ELF_DEFINE_ET(ET_DYN, 3, "Shared object") \ _ELF_DEFINE_ET(ET_CORE, 4, "Core file") \ _ELF_DEFINE_ET(ET_LOOS, 0xFE00U, "Begin OS-specific range") \ _ELF_DEFINE_ET(ET_HIOS, 0xFEFFU, "End OS-specific range") \ _ELF_DEFINE_ET(ET_LOPROC, 0xFF00U, "Begin processor-specific range") \ _ELF_DEFINE_ET(ET_HIPROC, 0xFFFFU, "End processor-specific range") #undef _ELF_DEFINE_ET #define _ELF_DEFINE_ET(N, V, DESCR) N = V , enum { _ELF_DEFINE_ELF_TYPES() ET__LAST__ }; /* ELF file format version numbers. */ #define EV_NONE 0 #define EV_CURRENT 1 /* * Flags for section groups. */ #define GRP_COMDAT 0x1 /* COMDAT semantics */ #define GRP_MASKOS 0x0ff00000 /* OS-specific flags */ #define GRP_MASKPROC 0xf0000000 /* processor-specific flags */ /* * Flags used by program header table entries. */ #define _ELF_DEFINE_PHDR_FLAGS() \ _ELF_DEFINE_PF(PF_X, 0x1, "Execute") \ _ELF_DEFINE_PF(PF_W, 0x2, "Write") \ _ELF_DEFINE_PF(PF_R, 0x4, "Read") \ _ELF_DEFINE_PF(PF_MASKOS, 0x0ff00000, "OS-specific flags") \ _ELF_DEFINE_PF(PF_MASKPROC, 0xf0000000, "Processor-specific flags") \ _ELF_DEFINE_PF(PF_ARM_SB, 0x10000000, \ "segment contains the location addressed by the static base") \ _ELF_DEFINE_PF(PF_ARM_PI, 0x20000000, \ "segment is position-independent") \ _ELF_DEFINE_PF(PF_ARM_ABS, 0x40000000, \ "segment must be loaded at its base address") #undef _ELF_DEFINE_PF #define _ELF_DEFINE_PF(N, V, DESCR) N = V , enum { _ELF_DEFINE_PHDR_FLAGS() PF__LAST__ }; /* * Types of program header table entries. */ #define _ELF_DEFINE_PHDR_TYPES() \ _ELF_DEFINE_PT(PT_NULL, 0, "ignored entry") \ _ELF_DEFINE_PT(PT_LOAD, 1, "loadable segment") \ _ELF_DEFINE_PT(PT_DYNAMIC, 2, \ "contains dynamic linking information") \ _ELF_DEFINE_PT(PT_INTERP, 3, "names an interpreter") \ _ELF_DEFINE_PT(PT_NOTE, 4, "auxiliary information") \ _ELF_DEFINE_PT(PT_SHLIB, 5, "reserved") \ _ELF_DEFINE_PT(PT_PHDR, 6, \ "describes the program header itself") \ _ELF_DEFINE_PT(PT_TLS, 7, "thread local storage") \ _ELF_DEFINE_PT(PT_LOOS, 0x60000000UL, \ "start of OS-specific range") \ _ELF_DEFINE_PT(PT_SUNW_UNWIND, 0x6464E550UL, \ "Solaris/amd64 stack unwind tables") \ _ELF_DEFINE_PT(PT_GNU_EH_FRAME, 0x6474E550UL, \ "GCC generated .eh_frame_hdr segment") \ _ELF_DEFINE_PT(PT_GNU_STACK, 0x6474E551UL, \ "Stack flags") \ _ELF_DEFINE_PT(PT_GNU_RELRO, 0x6474E552UL, \ "Segment becomes read-only after relocation") \ _ELF_DEFINE_PT(PT_SUNWBSS, 0x6FFFFFFAUL, \ "A Solaris .SUNW_bss section") \ _ELF_DEFINE_PT(PT_SUNWSTACK, 0x6FFFFFFBUL, \ "A Solaris process stack") \ _ELF_DEFINE_PT(PT_SUNWDTRACE, 0x6FFFFFFCUL, \ "Used by dtrace(1)") \ _ELF_DEFINE_PT(PT_SUNWCAP, 0x6FFFFFFDUL, \ "Special hardware capability requirements") \ _ELF_DEFINE_PT(PT_HIOS, 0x6FFFFFFFUL, \ "end of OS-specific range") \ _ELF_DEFINE_PT(PT_LOPROC, 0x70000000UL, \ "start of processor-specific range") \ _ELF_DEFINE_PT(PT_ARM_ARCHEXT, 0x70000000UL, \ "platform architecture compatibility information") \ _ELF_DEFINE_PT(PT_ARM_EXIDX, 0x70000001UL, \ "exception unwind tables") \ _ELF_DEFINE_PT(PT_MIPS_REGINFO, 0x70000000UL, \ "register usage information") \ _ELF_DEFINE_PT(PT_MIPS_RTPROC, 0x70000001UL, \ "runtime procedure table") \ _ELF_DEFINE_PT(PT_MIPS_OPTIONS, 0x70000002UL, \ "options segment") \ _ELF_DEFINE_PT(PT_HIPROC, 0x7FFFFFFFUL, \ "end of processor-specific range") #undef _ELF_DEFINE_PT #define _ELF_DEFINE_PT(N, V, DESCR) N = V , enum { _ELF_DEFINE_PHDR_TYPES() PT__LAST__ = PT_HIPROC }; /* synonyms. */ #define PT_ARM_UNWIND PT_ARM_EXIDX #define PT_HISUNW PT_HIOS #define PT_LOSUNW PT_SUNWBSS /* * Section flags. */ #define _ELF_DEFINE_SECTION_FLAGS() \ _ELF_DEFINE_SHF(SHF_WRITE, 0x1, \ "writable during program execution") \ _ELF_DEFINE_SHF(SHF_ALLOC, 0x2, \ "occupies memory during program execution") \ _ELF_DEFINE_SHF(SHF_EXECINSTR, 0x4, "executable instructions") \ _ELF_DEFINE_SHF(SHF_MERGE, 0x10, \ "may be merged to prevent duplication") \ _ELF_DEFINE_SHF(SHF_STRINGS, 0x20, \ "NUL-terminated character strings") \ _ELF_DEFINE_SHF(SHF_INFO_LINK, 0x40, \ "the sh_info field holds a link") \ _ELF_DEFINE_SHF(SHF_LINK_ORDER, 0x80, \ "special ordering requirements during linking") \ _ELF_DEFINE_SHF(SHF_OS_NONCONFORMING, 0x100, \ "requires OS-specific processing during linking") \ _ELF_DEFINE_SHF(SHF_GROUP, 0x200, \ "member of a section group") \ _ELF_DEFINE_SHF(SHF_TLS, 0x400, \ "holds thread-local storage") \ _ELF_DEFINE_SHF(SHF_COMPRESSED, 0x800, \ "holds compressed data") \ _ELF_DEFINE_SHF(SHF_MASKOS, 0x0FF00000UL, \ "bits reserved for OS-specific semantics") \ _ELF_DEFINE_SHF(SHF_AMD64_LARGE, 0x10000000UL, \ "section uses large code model") \ _ELF_DEFINE_SHF(SHF_ENTRYSECT, 0x10000000UL, \ "section contains an entry point (ARM)") \ _ELF_DEFINE_SHF(SHF_COMDEF, 0x80000000UL, \ "section may be multiply defined in input to link step (ARM)") \ _ELF_DEFINE_SHF(SHF_MIPS_GPREL, 0x10000000UL, \ "section must be part of global data area") \ _ELF_DEFINE_SHF(SHF_MIPS_MERGE, 0x20000000UL, \ "section data should be merged to eliminate duplication") \ _ELF_DEFINE_SHF(SHF_MIPS_ADDR, 0x40000000UL, \ "section data is addressed by default") \ _ELF_DEFINE_SHF(SHF_MIPS_STRING, 0x80000000UL, \ "section data is string data by default") \ _ELF_DEFINE_SHF(SHF_MIPS_NOSTRIP, 0x08000000UL, \ "section data may not be stripped") \ _ELF_DEFINE_SHF(SHF_MIPS_LOCAL, 0x04000000UL, \ "section data local to process") \ _ELF_DEFINE_SHF(SHF_MIPS_NAMES, 0x02000000UL, \ "linker must generate implicit hidden weak names") \ _ELF_DEFINE_SHF(SHF_MIPS_NODUPE, 0x01000000UL, \ "linker must retain only one copy") \ _ELF_DEFINE_SHF(SHF_ORDERED, 0x40000000UL, \ "section is ordered with respect to other sections") \ _ELF_DEFINE_SHF(SHF_EXCLUDE, 0x80000000UL, \ "section is excluded from executables and shared objects") \ _ELF_DEFINE_SHF(SHF_MASKPROC, 0xF0000000UL, \ "bits reserved for processor-specific semantics") #undef _ELF_DEFINE_SHF #define _ELF_DEFINE_SHF(N, V, DESCR) N = V , enum { _ELF_DEFINE_SECTION_FLAGS() SHF__LAST__ }; /* * Special section indices. */ #define _ELF_DEFINE_SECTION_INDICES() \ _ELF_DEFINE_SHN(SHN_UNDEF, 0, "undefined section") \ _ELF_DEFINE_SHN(SHN_LORESERVE, 0xFF00U, "start of reserved area") \ _ELF_DEFINE_SHN(SHN_LOPROC, 0xFF00U, \ "start of processor-specific range") \ _ELF_DEFINE_SHN(SHN_BEFORE, 0xFF00U, "used for section ordering") \ _ELF_DEFINE_SHN(SHN_AFTER, 0xFF01U, "used for section ordering") \ _ELF_DEFINE_SHN(SHN_AMD64_LCOMMON, 0xFF02U, "large common block label") \ _ELF_DEFINE_SHN(SHN_MIPS_ACOMMON, 0xFF00U, \ "allocated common symbols in a DSO") \ _ELF_DEFINE_SHN(SHN_MIPS_TEXT, 0xFF01U, "Reserved (obsolete)") \ _ELF_DEFINE_SHN(SHN_MIPS_DATA, 0xFF02U, "Reserved (obsolete)") \ _ELF_DEFINE_SHN(SHN_MIPS_SCOMMON, 0xFF03U, \ "gp-addressable common symbols") \ _ELF_DEFINE_SHN(SHN_MIPS_SUNDEFINED, 0xFF04U, \ "gp-addressable undefined symbols") \ _ELF_DEFINE_SHN(SHN_MIPS_LCOMMON, 0xFF05U, "local common symbols") \ _ELF_DEFINE_SHN(SHN_MIPS_LUNDEFINED, 0xFF06U, \ "local undefined symbols") \ _ELF_DEFINE_SHN(SHN_HIPROC, 0xFF1FU, \ "end of processor-specific range") \ _ELF_DEFINE_SHN(SHN_LOOS, 0xFF20U, \ "start of OS-specific range") \ _ELF_DEFINE_SHN(SHN_SUNW_IGNORE, 0xFF3FU, "used by dtrace") \ _ELF_DEFINE_SHN(SHN_HIOS, 0xFF3FU, \ "end of OS-specific range") \ _ELF_DEFINE_SHN(SHN_ABS, 0xFFF1U, "absolute references") \ _ELF_DEFINE_SHN(SHN_COMMON, 0xFFF2U, "references to COMMON areas") \ _ELF_DEFINE_SHN(SHN_XINDEX, 0xFFFFU, "extended index") \ _ELF_DEFINE_SHN(SHN_HIRESERVE, 0xFFFFU, "end of reserved area") #undef _ELF_DEFINE_SHN #define _ELF_DEFINE_SHN(N, V, DESCR) N = V , enum { _ELF_DEFINE_SECTION_INDICES() SHN__LAST__ }; /* * Section types. */ #define _ELF_DEFINE_SECTION_TYPES() \ _ELF_DEFINE_SHT(SHT_NULL, 0, "inactive header") \ _ELF_DEFINE_SHT(SHT_PROGBITS, 1, "program defined information") \ _ELF_DEFINE_SHT(SHT_SYMTAB, 2, "symbol table") \ _ELF_DEFINE_SHT(SHT_STRTAB, 3, "string table") \ _ELF_DEFINE_SHT(SHT_RELA, 4, \ "relocation entries with addends") \ _ELF_DEFINE_SHT(SHT_HASH, 5, "symbol hash table") \ _ELF_DEFINE_SHT(SHT_DYNAMIC, 6, \ "information for dynamic linking") \ _ELF_DEFINE_SHT(SHT_NOTE, 7, "additional notes") \ _ELF_DEFINE_SHT(SHT_NOBITS, 8, "section occupying no space") \ _ELF_DEFINE_SHT(SHT_REL, 9, \ "relocation entries without addends") \ _ELF_DEFINE_SHT(SHT_SHLIB, 10, "reserved") \ _ELF_DEFINE_SHT(SHT_DYNSYM, 11, "symbol table") \ _ELF_DEFINE_SHT(SHT_INIT_ARRAY, 14, \ "pointers to initialization functions") \ _ELF_DEFINE_SHT(SHT_FINI_ARRAY, 15, \ "pointers to termination functions") \ _ELF_DEFINE_SHT(SHT_PREINIT_ARRAY, 16, \ "pointers to functions called before initialization") \ _ELF_DEFINE_SHT(SHT_GROUP, 17, "defines a section group") \ _ELF_DEFINE_SHT(SHT_SYMTAB_SHNDX, 18, \ "used for extended section numbering") \ _ELF_DEFINE_SHT(SHT_LOOS, 0x60000000UL, \ "start of OS-specific range") \ _ELF_DEFINE_SHT(SHT_SUNW_dof, 0x6FFFFFF4UL, \ "used by dtrace") \ _ELF_DEFINE_SHT(SHT_SUNW_cap, 0x6FFFFFF5UL, \ "capability requirements") \ _ELF_DEFINE_SHT(SHT_GNU_ATTRIBUTES, 0x6FFFFFF5UL, \ "object attributes") \ _ELF_DEFINE_SHT(SHT_SUNW_SIGNATURE, 0x6FFFFFF6UL, \ "module verification signature") \ _ELF_DEFINE_SHT(SHT_GNU_HASH, 0x6FFFFFF6UL, \ "GNU Hash sections") \ _ELF_DEFINE_SHT(SHT_GNU_LIBLIST, 0x6FFFFFF7UL, \ "List of libraries to be prelinked") \ _ELF_DEFINE_SHT(SHT_SUNW_ANNOTATE, 0x6FFFFFF7UL, \ "special section where unresolved references are allowed") \ _ELF_DEFINE_SHT(SHT_SUNW_DEBUGSTR, 0x6FFFFFF8UL, \ "debugging information") \ _ELF_DEFINE_SHT(SHT_CHECKSUM, 0x6FFFFFF8UL, \ "checksum for dynamic shared objects") \ _ELF_DEFINE_SHT(SHT_SUNW_DEBUG, 0x6FFFFFF9UL, \ "debugging information") \ _ELF_DEFINE_SHT(SHT_SUNW_move, 0x6FFFFFFAUL, \ "information to handle partially initialized symbols") \ _ELF_DEFINE_SHT(SHT_SUNW_COMDAT, 0x6FFFFFFBUL, \ "section supporting merging of multiple copies of data") \ _ELF_DEFINE_SHT(SHT_SUNW_syminfo, 0x6FFFFFFCUL, \ "additional symbol information") \ _ELF_DEFINE_SHT(SHT_SUNW_verdef, 0x6FFFFFFDUL, \ "symbol versioning information") \ _ELF_DEFINE_SHT(SHT_SUNW_verneed, 0x6FFFFFFEUL, \ "symbol versioning requirements") \ _ELF_DEFINE_SHT(SHT_SUNW_versym, 0x6FFFFFFFUL, \ "symbol versioning table") \ _ELF_DEFINE_SHT(SHT_HIOS, 0x6FFFFFFFUL, \ "end of OS-specific range") \ _ELF_DEFINE_SHT(SHT_LOPROC, 0x70000000UL, \ "start of processor-specific range") \ _ELF_DEFINE_SHT(SHT_ARM_EXIDX, 0x70000001UL, \ "exception index table") \ _ELF_DEFINE_SHT(SHT_ARM_PREEMPTMAP, 0x70000002UL, \ "BPABI DLL dynamic linking preemption map") \ _ELF_DEFINE_SHT(SHT_ARM_ATTRIBUTES, 0x70000003UL, \ "object file compatibility attributes") \ _ELF_DEFINE_SHT(SHT_ARM_DEBUGOVERLAY, 0x70000004UL, \ "overlay debug information") \ _ELF_DEFINE_SHT(SHT_ARM_OVERLAYSECTION, 0x70000005UL, \ "overlay debug information") \ _ELF_DEFINE_SHT(SHT_MIPS_LIBLIST, 0x70000000UL, \ "DSO library information used in link") \ _ELF_DEFINE_SHT(SHT_MIPS_MSYM, 0x70000001UL, \ "MIPS symbol table extension") \ _ELF_DEFINE_SHT(SHT_MIPS_CONFLICT, 0x70000002UL, \ "symbol conflicting with DSO-defined symbols ") \ _ELF_DEFINE_SHT(SHT_MIPS_GPTAB, 0x70000003UL, \ "global pointer table") \ _ELF_DEFINE_SHT(SHT_MIPS_UCODE, 0x70000004UL, \ "reserved") \ _ELF_DEFINE_SHT(SHT_MIPS_DEBUG, 0x70000005UL, \ "reserved (obsolete debug information)") \ _ELF_DEFINE_SHT(SHT_MIPS_REGINFO, 0x70000006UL, \ "register usage information") \ _ELF_DEFINE_SHT(SHT_MIPS_PACKAGE, 0x70000007UL, \ "OSF reserved") \ _ELF_DEFINE_SHT(SHT_MIPS_PACKSYM, 0x70000008UL, \ "OSF reserved") \ _ELF_DEFINE_SHT(SHT_MIPS_RELD, 0x70000009UL, \ "dynamic relocation") \ _ELF_DEFINE_SHT(SHT_MIPS_IFACE, 0x7000000BUL, \ "subprogram interface information") \ _ELF_DEFINE_SHT(SHT_MIPS_CONTENT, 0x7000000CUL, \ "section content classification") \ _ELF_DEFINE_SHT(SHT_MIPS_OPTIONS, 0x7000000DUL, \ "general options") \ _ELF_DEFINE_SHT(SHT_MIPS_DELTASYM, 0x7000001BUL, \ "Delta C++: symbol table") \ _ELF_DEFINE_SHT(SHT_MIPS_DELTAINST, 0x7000001CUL, \ "Delta C++: instance table") \ _ELF_DEFINE_SHT(SHT_MIPS_DELTACLASS, 0x7000001DUL, \ "Delta C++: class table") \ _ELF_DEFINE_SHT(SHT_MIPS_DWARF, 0x7000001EUL, \ "DWARF debug information") \ _ELF_DEFINE_SHT(SHT_MIPS_DELTADECL, 0x7000001FUL, \ "Delta C++: declarations") \ _ELF_DEFINE_SHT(SHT_MIPS_SYMBOL_LIB, 0x70000020UL, \ "symbol-to-library mapping") \ _ELF_DEFINE_SHT(SHT_MIPS_EVENTS, 0x70000021UL, \ "event locations") \ _ELF_DEFINE_SHT(SHT_MIPS_TRANSLATE, 0x70000022UL, \ "???") \ _ELF_DEFINE_SHT(SHT_MIPS_PIXIE, 0x70000023UL, \ "special pixie sections") \ _ELF_DEFINE_SHT(SHT_MIPS_XLATE, 0x70000024UL, \ "address translation table") \ _ELF_DEFINE_SHT(SHT_MIPS_XLATE_DEBUG, 0x70000025UL, \ "SGI internal address translation table") \ _ELF_DEFINE_SHT(SHT_MIPS_WHIRL, 0x70000026UL, \ "intermediate code") \ _ELF_DEFINE_SHT(SHT_MIPS_EH_REGION, 0x70000027UL, \ "C++ exception handling region info") \ _ELF_DEFINE_SHT(SHT_MIPS_XLATE_OLD, 0x70000028UL, \ "obsolete") \ _ELF_DEFINE_SHT(SHT_MIPS_PDR_EXCEPTION, 0x70000029UL, \ "runtime procedure descriptor table exception information") \ _ELF_DEFINE_SHT(SHT_SPARC_GOTDATA, 0x70000000UL, \ "SPARC-specific data") \ _ELF_DEFINE_SHT(SHT_AMD64_UNWIND, 0x70000001UL, \ "unwind tables for the AMD64") \ _ELF_DEFINE_SHT(SHT_ORDERED, 0x7FFFFFFFUL, \ "sort entries in the section") \ _ELF_DEFINE_SHT(SHT_HIPROC, 0x7FFFFFFFUL, \ "end of processor-specific range") \ _ELF_DEFINE_SHT(SHT_LOUSER, 0x80000000UL, \ "start of application-specific range") \ _ELF_DEFINE_SHT(SHT_HIUSER, 0xFFFFFFFFUL, \ "end of application-specific range") #undef _ELF_DEFINE_SHT #define _ELF_DEFINE_SHT(N, V, DESCR) N = V , enum { _ELF_DEFINE_SECTION_TYPES() SHT__LAST__ = SHT_HIUSER }; /* Aliases for section types. */ #define SHT_GNU_verdef SHT_SUNW_verdef #define SHT_GNU_verneed SHT_SUNW_verneed #define SHT_GNU_versym SHT_SUNW_versym /* * Symbol binding information. */ #define _ELF_DEFINE_SYMBOL_BINDING() \ _ELF_DEFINE_STB(STB_LOCAL, 0, \ "not visible outside defining object file") \ _ELF_DEFINE_STB(STB_GLOBAL, 1, \ "visible across all object files being combined") \ _ELF_DEFINE_STB(STB_WEAK, 2, \ "visible across all object files but with low precedence") \ _ELF_DEFINE_STB(STB_LOOS, 10, "start of OS-specific range") \ _ELF_DEFINE_STB(STB_HIOS, 12, "end of OS-specific range") \ _ELF_DEFINE_STB(STB_LOPROC, 13, \ "start of processor-specific range") \ _ELF_DEFINE_STB(STB_HIPROC, 15, \ "end of processor-specific range") #undef _ELF_DEFINE_STB #define _ELF_DEFINE_STB(N, V, DESCR) N = V , enum { _ELF_DEFINE_SYMBOL_BINDING() STB__LAST__ }; /* * Symbol types */ #define _ELF_DEFINE_SYMBOL_TYPES() \ _ELF_DEFINE_STT(STT_NOTYPE, 0, "unspecified type") \ _ELF_DEFINE_STT(STT_OBJECT, 1, "data object") \ _ELF_DEFINE_STT(STT_FUNC, 2, "executable code") \ _ELF_DEFINE_STT(STT_SECTION, 3, "section") \ _ELF_DEFINE_STT(STT_FILE, 4, "source file") \ _ELF_DEFINE_STT(STT_COMMON, 5, "uninitialized common block") \ _ELF_DEFINE_STT(STT_TLS, 6, "thread local storage") \ _ELF_DEFINE_STT(STT_LOOS, 10, "start of OS-specific types") \ _ELF_DEFINE_STT(STT_HIOS, 12, "end of OS-specific types") \ _ELF_DEFINE_STT(STT_LOPROC, 13, \ "start of processor-specific types") \ _ELF_DEFINE_STT(STT_ARM_TFUNC, 13, "Thumb function (GNU)") \ _ELF_DEFINE_STT(STT_ARM_16BIT, 15, "Thumb label (GNU)") \ _ELF_DEFINE_STT(STT_HIPROC, 15, \ "end of processor-specific types") #undef _ELF_DEFINE_STT #define _ELF_DEFINE_STT(N, V, DESCR) N = V , enum { _ELF_DEFINE_SYMBOL_TYPES() STT__LAST__ }; /* * Symbol binding. */ #define _ELF_DEFINE_SYMBOL_BINDING_KINDS() \ _ELF_DEFINE_SYB(SYMINFO_BT_SELF, 0xFFFFU, \ "bound to self") \ _ELF_DEFINE_SYB(SYMINFO_BT_PARENT, 0xFFFEU, \ "bound to parent") \ _ELF_DEFINE_SYB(SYMINFO_BT_NONE, 0xFFFDU, \ "no special binding") #undef _ELF_DEFINE_SYB #define _ELF_DEFINE_SYB(N, V, DESCR) N = V , enum { _ELF_DEFINE_SYMBOL_BINDING_KINDS() SYMINFO__LAST__ }; /* * Symbol visibility. */ #define _ELF_DEFINE_SYMBOL_VISIBILITY() \ _ELF_DEFINE_STV(STV_DEFAULT, 0, \ "as specified by symbol type") \ _ELF_DEFINE_STV(STV_INTERNAL, 1, \ "as defined by processor semantics") \ _ELF_DEFINE_STV(STV_HIDDEN, 2, \ "hidden from other components") \ _ELF_DEFINE_STV(STV_PROTECTED, 3, \ "local references are not preemptable") #undef _ELF_DEFINE_STV #define _ELF_DEFINE_STV(N, V, DESCR) N = V , enum { _ELF_DEFINE_SYMBOL_VISIBILITY() STV__LAST__ }; /* * Symbol flags. */ #define _ELF_DEFINE_SYMBOL_FLAGS() \ _ELF_DEFINE_SYF(SYMINFO_FLG_DIRECT, 0x01, \ "directly assocated reference") \ _ELF_DEFINE_SYF(SYMINFO_FLG_COPY, 0x04, \ "definition by copy-relocation") \ _ELF_DEFINE_SYF(SYMINFO_FLG_LAZYLOAD, 0x08, \ "object should be lazily loaded") \ _ELF_DEFINE_SYF(SYMINFO_FLG_DIRECTBIND, 0x10, \ "reference should be directly bound") \ _ELF_DEFINE_SYF(SYMINFO_FLG_NOEXTDIRECT, 0x20, \ "external references not allowed to bind to definition") #undef _ELF_DEFINE_SYF #define _ELF_DEFINE_SYF(N, V, DESCR) N = V , enum { _ELF_DEFINE_SYMBOL_FLAGS() SYMINFO_FLG__LAST__ }; /* * Version dependencies. */ #define _ELF_DEFINE_VERSIONING_DEPENDENCIES() \ _ELF_DEFINE_VERD(VER_NDX_LOCAL, 0, "local scope") \ _ELF_DEFINE_VERD(VER_NDX_GLOBAL, 1, "global scope") #undef _ELF_DEFINE_VERD #define _ELF_DEFINE_VERD(N, V, DESCR) N = V , enum { _ELF_DEFINE_VERSIONING_DEPENDENCIES() VER_NDX__LAST__ }; /* * Version flags. */ #define _ELF_DEFINE_VERSIONING_FLAGS() \ _ELF_DEFINE_VERF(VER_FLG_BASE, 0x1, "file version") \ _ELF_DEFINE_VERF(VER_FLG_WEAK, 0x2, "weak version") #undef _ELF_DEFINE_VERF #define _ELF_DEFINE_VERF(N, V, DESCR) N = V , enum { _ELF_DEFINE_VERSIONING_FLAGS() VER_FLG__LAST__ }; /* * Version needs */ #define _ELF_DEFINE_VERSIONING_NEEDS() \ _ELF_DEFINE_VRN(VER_NEED_NONE, 0, "invalid version") \ _ELF_DEFINE_VRN(VER_NEED_CURRENT, 1, "current version") #undef _ELF_DEFINE_VRN #define _ELF_DEFINE_VRN(N, V, DESCR) N = V , enum { _ELF_DEFINE_VERSIONING_NEEDS() VER_NEED__LAST__ }; /* * Version numbers. */ #define _ELF_DEFINE_VERSIONING_NUMBERS() \ _ELF_DEFINE_VRNU(VER_DEF_NONE, 0, "invalid version") \ _ELF_DEFINE_VRNU(VER_DEF_CURRENT, 1, "current version") #undef _ELF_DEFINE_VRNU #define _ELF_DEFINE_VRNU(N, V, DESCR) N = V , enum { _ELF_DEFINE_VERSIONING_NUMBERS() VER_DEF__LAST__ }; /** ** Relocation types. **/ #define _ELF_DEFINE_386_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_386_NONE, 0) \ _ELF_DEFINE_RELOC(R_386_32, 1) \ _ELF_DEFINE_RELOC(R_386_PC32, 2) \ _ELF_DEFINE_RELOC(R_386_GOT32, 3) \ _ELF_DEFINE_RELOC(R_386_PLT32, 4) \ _ELF_DEFINE_RELOC(R_386_COPY, 5) \ _ELF_DEFINE_RELOC(R_386_GLOB_DAT, 6) \ _ELF_DEFINE_RELOC(R_386_JMP_SLOT, 7) \ _ELF_DEFINE_RELOC(R_386_RELATIVE, 8) \ _ELF_DEFINE_RELOC(R_386_GOTOFF, 9) \ _ELF_DEFINE_RELOC(R_386_GOTPC, 10) \ _ELF_DEFINE_RELOC(R_386_32PLT, 11) \ _ELF_DEFINE_RELOC(R_386_16, 20) \ _ELF_DEFINE_RELOC(R_386_PC16, 21) \ _ELF_DEFINE_RELOC(R_386_8, 22) \ _ELF_DEFINE_RELOC(R_386_PC8, 23) /* */ #define _ELF_DEFINE_AARCH64_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_AARCH64_ABS64, 257) \ _ELF_DEFINE_RELOC(R_AARCH64_ABS32, 258) \ /* * These are the symbols used in the Sun ``Linkers and Loaders * Guide'', Document No: 817-1984-17. See the X86_64 relocations list * below for the spellings used in the ELF specification. */ #define _ELF_DEFINE_AMD64_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_AMD64_NONE, 0) \ _ELF_DEFINE_RELOC(R_AMD64_64, 1) \ _ELF_DEFINE_RELOC(R_AMD64_PC32, 2) \ _ELF_DEFINE_RELOC(R_AMD64_GOT32, 3) \ _ELF_DEFINE_RELOC(R_AMD64_PLT32, 4) \ _ELF_DEFINE_RELOC(R_AMD64_COPY, 5) \ _ELF_DEFINE_RELOC(R_AMD64_GLOB_DAT, 6) \ _ELF_DEFINE_RELOC(R_AMD64_JUMP_SLOT, 7) \ _ELF_DEFINE_RELOC(R_AMD64_RELATIVE, 8) \ _ELF_DEFINE_RELOC(R_AMD64_GOTPCREL, 9) \ _ELF_DEFINE_RELOC(R_AMD64_32, 10) \ _ELF_DEFINE_RELOC(R_AMD64_32S, 11) \ _ELF_DEFINE_RELOC(R_AMD64_16, 12) \ _ELF_DEFINE_RELOC(R_AMD64_PC16, 13) \ _ELF_DEFINE_RELOC(R_AMD64_8, 14) \ _ELF_DEFINE_RELOC(R_AMD64_PC8, 15) \ _ELF_DEFINE_RELOC(R_AMD64_PC64, 24) \ _ELF_DEFINE_RELOC(R_AMD64_GOTOFF64, 25) \ _ELF_DEFINE_RELOC(R_AMD64_GOTPC32, 26) /* * Relocation definitions from the ARM ELF ABI, version "ARM IHI * 0044E" released on 30th November 2012. */ #define _ELF_DEFINE_ARM_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_ARM_NONE, 0) \ _ELF_DEFINE_RELOC(R_ARM_PC24, 1) \ _ELF_DEFINE_RELOC(R_ARM_ABS32, 2) \ _ELF_DEFINE_RELOC(R_ARM_REL32, 3) \ _ELF_DEFINE_RELOC(R_ARM_LDR_PC_G0, 4) \ _ELF_DEFINE_RELOC(R_ARM_ABS16, 5) \ _ELF_DEFINE_RELOC(R_ARM_ABS12, 6) \ _ELF_DEFINE_RELOC(R_ARM_THM_ABS5, 7) \ _ELF_DEFINE_RELOC(R_ARM_ABS8, 8) \ _ELF_DEFINE_RELOC(R_ARM_SBREL32, 9) \ _ELF_DEFINE_RELOC(R_ARM_THM_CALL, 10) \ _ELF_DEFINE_RELOC(R_ARM_THM_PC8, 11) \ _ELF_DEFINE_RELOC(R_ARM_BREL_ADJ, 12) \ _ELF_DEFINE_RELOC(R_ARM_SWI24, 13) \ _ELF_DEFINE_RELOC(R_ARM_TLS_DESC, 13) \ _ELF_DEFINE_RELOC(R_ARM_THM_SWI8, 14) \ _ELF_DEFINE_RELOC(R_ARM_XPC25, 15) \ _ELF_DEFINE_RELOC(R_ARM_THM_XPC22, 16) \ _ELF_DEFINE_RELOC(R_ARM_TLS_DTPMOD32, 17) \ _ELF_DEFINE_RELOC(R_ARM_TLS_DTPOFF32, 18) \ _ELF_DEFINE_RELOC(R_ARM_TLS_TPOFF32, 19) \ _ELF_DEFINE_RELOC(R_ARM_COPY, 20) \ _ELF_DEFINE_RELOC(R_ARM_GLOB_DAT, 21) \ _ELF_DEFINE_RELOC(R_ARM_JUMP_SLOT, 22) \ _ELF_DEFINE_RELOC(R_ARM_RELATIVE, 23) \ _ELF_DEFINE_RELOC(R_ARM_GOTOFF32, 24) \ _ELF_DEFINE_RELOC(R_ARM_BASE_PREL, 25) \ _ELF_DEFINE_RELOC(R_ARM_GOT_BREL, 26) \ _ELF_DEFINE_RELOC(R_ARM_PLT32, 27) \ _ELF_DEFINE_RELOC(R_ARM_CALL, 28) \ _ELF_DEFINE_RELOC(R_ARM_JUMP24, 29) \ _ELF_DEFINE_RELOC(R_ARM_THM_JUMP24, 30) \ _ELF_DEFINE_RELOC(R_ARM_BASE_ABS, 31) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_7_0, 32) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_15_8, 33) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PCREL_23_15, 34) \ _ELF_DEFINE_RELOC(R_ARM_LDR_SBREL_11_0_NC, 35) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SBREL_19_12_NC, 36) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SBREL_27_20_CK, 37) \ _ELF_DEFINE_RELOC(R_ARM_TARGET1, 38) \ _ELF_DEFINE_RELOC(R_ARM_SBREL31, 39) \ _ELF_DEFINE_RELOC(R_ARM_V4BX, 40) \ _ELF_DEFINE_RELOC(R_ARM_TARGET2, 41) \ _ELF_DEFINE_RELOC(R_ARM_PREL31, 42) \ _ELF_DEFINE_RELOC(R_ARM_MOVW_ABS_NC, 43) \ _ELF_DEFINE_RELOC(R_ARM_MOVT_ABS, 44) \ _ELF_DEFINE_RELOC(R_ARM_MOVW_PREL_NC, 45) \ _ELF_DEFINE_RELOC(R_ARM_MOVT_PREL, 46) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVW_ABS_NC, 47) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVT_ABS, 48) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVW_PREL_NC, 49) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVT_PREL, 50) \ _ELF_DEFINE_RELOC(R_ARM_THM_JUMP19, 51) \ _ELF_DEFINE_RELOC(R_ARM_THM_JUMP6, 52) \ _ELF_DEFINE_RELOC(R_ARM_THM_ALU_PREL_11_0, 53) \ _ELF_DEFINE_RELOC(R_ARM_THM_PC12, 54) \ _ELF_DEFINE_RELOC(R_ARM_ABS32_NOI, 55) \ _ELF_DEFINE_RELOC(R_ARM_REL32_NOI, 56) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PC_G0_NC, 57) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PC_G0, 58) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PC_G1_NC, 59) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PC_G1, 60) \ _ELF_DEFINE_RELOC(R_ARM_ALU_PC_G2, 61) \ _ELF_DEFINE_RELOC(R_ARM_LDR_PC_G1, 62) \ _ELF_DEFINE_RELOC(R_ARM_LDR_PC_G2, 63) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G0, 64) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G1, 65) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_PC_G2, 66) \ _ELF_DEFINE_RELOC(R_ARM_LDC_PC_G0, 67) \ _ELF_DEFINE_RELOC(R_ARM_LDC_PC_G1, 68) \ _ELF_DEFINE_RELOC(R_ARM_LDC_PC_G2, 69) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SB_G0_NC, 70) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SB_G0, 71) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SB_G1_NC, 72) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SB_G1, 73) \ _ELF_DEFINE_RELOC(R_ARM_ALU_SB_G2, 74) \ _ELF_DEFINE_RELOC(R_ARM_LDR_SB_G0, 75) \ _ELF_DEFINE_RELOC(R_ARM_LDR_SB_G1, 76) \ _ELF_DEFINE_RELOC(R_ARM_LDR_SB_G2, 77) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G0, 78) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G1, 79) \ _ELF_DEFINE_RELOC(R_ARM_LDRS_SB_G2, 80) \ _ELF_DEFINE_RELOC(R_ARM_LDC_SB_G0, 81) \ _ELF_DEFINE_RELOC(R_ARM_LDC_SB_G1, 82) \ _ELF_DEFINE_RELOC(R_ARM_LDC_SB_G2, 83) \ _ELF_DEFINE_RELOC(R_ARM_MOVW_BREL_NC, 84) \ _ELF_DEFINE_RELOC(R_ARM_MOVT_BREL, 85) \ _ELF_DEFINE_RELOC(R_ARM_MOVW_BREL, 86) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVW_BREL_NC, 87) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVT_BREL, 88) \ _ELF_DEFINE_RELOC(R_ARM_THM_MOVW_BREL, 89) \ _ELF_DEFINE_RELOC(R_ARM_TLS_GOTDESC, 90) \ _ELF_DEFINE_RELOC(R_ARM_TLS_CALL, 91) \ _ELF_DEFINE_RELOC(R_ARM_TLS_DESCSEQ, 92) \ _ELF_DEFINE_RELOC(R_ARM_THM_TLS_CALL, 93) \ _ELF_DEFINE_RELOC(R_ARM_PLT32_ABS, 94) \ _ELF_DEFINE_RELOC(R_ARM_GOT_ABS, 95) \ _ELF_DEFINE_RELOC(R_ARM_GOT_PREL, 96) \ _ELF_DEFINE_RELOC(R_ARM_GOT_BREL12, 97) \ _ELF_DEFINE_RELOC(R_ARM_GOTOFF12, 98) \ _ELF_DEFINE_RELOC(R_ARM_GOTRELAX, 99) \ _ELF_DEFINE_RELOC(R_ARM_GNU_VTENTRY, 100) \ _ELF_DEFINE_RELOC(R_ARM_GNU_VTINHERIT, 101) \ _ELF_DEFINE_RELOC(R_ARM_THM_JUMP11, 102) \ _ELF_DEFINE_RELOC(R_ARM_THM_JUMP8, 103) \ _ELF_DEFINE_RELOC(R_ARM_TLS_GD32, 104) \ _ELF_DEFINE_RELOC(R_ARM_TLS_LDM32, 105) \ _ELF_DEFINE_RELOC(R_ARM_TLS_LDO32, 106) \ _ELF_DEFINE_RELOC(R_ARM_TLS_IE32, 107) \ _ELF_DEFINE_RELOC(R_ARM_TLS_LE32, 108) \ _ELF_DEFINE_RELOC(R_ARM_TLS_LDO12, 109) \ _ELF_DEFINE_RELOC(R_ARM_TLS_LE12, 110) \ _ELF_DEFINE_RELOC(R_ARM_TLS_IE12GP, 111) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_0, 112) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_1, 113) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_2, 114) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_3, 115) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_4, 116) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_5, 117) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_6, 118) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_7, 119) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_8, 120) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_9, 121) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_10, 122) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_11, 123) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_12, 124) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_13, 125) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_14, 126) \ _ELF_DEFINE_RELOC(R_ARM_PRIVATE_15, 127) \ _ELF_DEFINE_RELOC(R_ARM_ME_TOO, 128) \ _ELF_DEFINE_RELOC(R_ARM_THM_TLS_DESCSEQ16, 129) \ _ELF_DEFINE_RELOC(R_ARM_THM_TLS_DESCSEQ32, 130) \ _ELF_DEFINE_RELOC(R_ARM_THM_GOT_BREL12, 131) \ _ELF_DEFINE_RELOC(R_ARM_IRELATIVE, 140) #define _ELF_DEFINE_IA64_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_IA_64_NONE, 0) \ _ELF_DEFINE_RELOC(R_IA_64_IMM14, 0x21) \ _ELF_DEFINE_RELOC(R_IA_64_IMM22, 0x22) \ _ELF_DEFINE_RELOC(R_IA_64_IMM64, 0x23) \ _ELF_DEFINE_RELOC(R_IA_64_DIR32MSB, 0x24) \ _ELF_DEFINE_RELOC(R_IA_64_DIR32LSB, 0x25) \ _ELF_DEFINE_RELOC(R_IA_64_DIR64MSB, 0x26) \ _ELF_DEFINE_RELOC(R_IA_64_DIR64LSB, 0x27) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL22, 0x2a) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL64I, 0x2b) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL32MSB, 0x2c) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL32LSB, 0x2d) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL64MSB, 0x2e) \ _ELF_DEFINE_RELOC(R_IA_64_GPREL64LSB, 0x2f) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF22, 0x32) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF64I, 0x33) \ _ELF_DEFINE_RELOC(R_IA_64_PLTOFF22, 0x3a) \ _ELF_DEFINE_RELOC(R_IA_64_PLTOFF64I, 0x3b) \ _ELF_DEFINE_RELOC(R_IA_64_PLTOFF64MSB, 0x3e) \ _ELF_DEFINE_RELOC(R_IA_64_PLTOFF64LSB, 0x3f) \ _ELF_DEFINE_RELOC(R_IA_64_FPTR64I, 0x43) \ _ELF_DEFINE_RELOC(R_IA_64_FPTR32MSB, 0x44) \ _ELF_DEFINE_RELOC(R_IA_64_FPTR32LSB, 0x45) \ _ELF_DEFINE_RELOC(R_IA_64_FPTR64MSB, 0x46) \ _ELF_DEFINE_RELOC(R_IA_64_FPTR64LSB, 0x47) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL60B, 0x48) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL21B, 0x49) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL21M, 0x4a) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL21F, 0x4b) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL32MSB, 0x4c) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL32LSB, 0x4d) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL64MSB, 0x4e) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL64LSB, 0x4f) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR22, 0x52) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64I, 0x53) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR32MSB, 0x54) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR32LSB, 0x55) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64MSB, 0x56) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_FPTR64LSB, 0x57) \ _ELF_DEFINE_RELOC(R_IA_64_SEGREL32MSB, 0x5c) \ _ELF_DEFINE_RELOC(R_IA_64_SEGREL32LSB, 0x5d) \ _ELF_DEFINE_RELOC(R_IA_64_SEGREL64MSB, 0x5e) \ _ELF_DEFINE_RELOC(R_IA_64_SEGREL64LSB, 0x5f) \ _ELF_DEFINE_RELOC(R_IA_64_SECREL32MSB, 0x64) \ _ELF_DEFINE_RELOC(R_IA_64_SECREL32LSB, 0x65) \ _ELF_DEFINE_RELOC(R_IA_64_SECREL64MSB, 0x66) \ _ELF_DEFINE_RELOC(R_IA_64_SECREL64LSB, 0x67) \ _ELF_DEFINE_RELOC(R_IA_64_REL32MSB, 0x6c) \ _ELF_DEFINE_RELOC(R_IA_64_REL32LSB, 0x6d) \ _ELF_DEFINE_RELOC(R_IA_64_REL64MSB, 0x6e) \ _ELF_DEFINE_RELOC(R_IA_64_REL64LSB, 0x6f) \ _ELF_DEFINE_RELOC(R_IA_64_LTV32MSB, 0x74) \ _ELF_DEFINE_RELOC(R_IA_64_LTV32LSB, 0x75) \ _ELF_DEFINE_RELOC(R_IA_64_LTV64MSB, 0x76) \ _ELF_DEFINE_RELOC(R_IA_64_LTV64LSB, 0x77) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL21BIa, 0x79) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL22, 0x7A) \ _ELF_DEFINE_RELOC(R_IA_64_PCREL64I, 0x7B) \ _ELF_DEFINE_RELOC(R_IA_64_IPLTMSB, 0x80) \ _ELF_DEFINE_RELOC(R_IA_64_IPLTLSB, 0x81) \ _ELF_DEFINE_RELOC(R_IA_64_SUB, 0x85) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF22X, 0x86) \ _ELF_DEFINE_RELOC(R_IA_64_LDXMOV, 0x87) \ _ELF_DEFINE_RELOC(R_IA_64_TPREL14, 0x91) \ _ELF_DEFINE_RELOC(R_IA_64_TPREL22, 0x92) \ _ELF_DEFINE_RELOC(R_IA_64_TPREL64I, 0x93) \ _ELF_DEFINE_RELOC(R_IA_64_TPREL64MSB, 0x96) \ _ELF_DEFINE_RELOC(R_IA_64_TPREL64LSB, 0x97) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_TPREL22, 0x9A) \ _ELF_DEFINE_RELOC(R_IA_64_DTPMOD64MSB, 0xA6) \ _ELF_DEFINE_RELOC(R_IA_64_DTPMOD64LSB, 0xA7) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_DTPMOD22, 0xAA) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL14, 0xB1) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL22, 0xB2) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL64I, 0xB3) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL32MSB, 0xB4) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL32LSB, 0xB5) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL64MSB, 0xB6) \ _ELF_DEFINE_RELOC(R_IA_64_DTPREL64LSB, 0xB7) \ _ELF_DEFINE_RELOC(R_IA_64_LTOFF_DTPREL22, 0xBA) #define _ELF_DEFINE_MIPS_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_MIPS_NONE, 0) \ _ELF_DEFINE_RELOC(R_MIPS_16, 1) \ _ELF_DEFINE_RELOC(R_MIPS_32, 2) \ _ELF_DEFINE_RELOC(R_MIPS_REL32, 3) \ _ELF_DEFINE_RELOC(R_MIPS_26, 4) \ _ELF_DEFINE_RELOC(R_MIPS_HI16, 5) \ _ELF_DEFINE_RELOC(R_MIPS_LO16, 6) \ _ELF_DEFINE_RELOC(R_MIPS_GPREL16, 7) \ _ELF_DEFINE_RELOC(R_MIPS_LITERAL, 8) \ _ELF_DEFINE_RELOC(R_MIPS_GOT16, 9) \ _ELF_DEFINE_RELOC(R_MIPS_PC16, 10) \ _ELF_DEFINE_RELOC(R_MIPS_CALL16, 11) \ _ELF_DEFINE_RELOC(R_MIPS_GPREL32, 12) \ _ELF_DEFINE_RELOC(R_MIPS_64, 18) \ _ELF_DEFINE_RELOC(R_MIPS_GOTHI16, 21) \ _ELF_DEFINE_RELOC(R_MIPS_GOTLO16, 22) \ _ELF_DEFINE_RELOC(R_MIPS_CALLHI16, 30) \ _ELF_DEFINE_RELOC(R_MIPS_CALLLO16, 31) #define _ELF_DEFINE_PPC32_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_PPC_NONE, 0) \ _ELF_DEFINE_RELOC(R_PPC_ADDR32, 1) \ _ELF_DEFINE_RELOC(R_PPC_ADDR24, 2) \ _ELF_DEFINE_RELOC(R_PPC_ADDR16, 3) \ _ELF_DEFINE_RELOC(R_PPC_ADDR16_LO, 4) \ _ELF_DEFINE_RELOC(R_PPC_ADDR16_HI, 5) \ _ELF_DEFINE_RELOC(R_PPC_ADDR16_HA, 6) \ _ELF_DEFINE_RELOC(R_PPC_ADDR14, 7) \ _ELF_DEFINE_RELOC(R_PPC_ADDR14_BRTAKEN, 8) \ _ELF_DEFINE_RELOC(R_PPC_ADDR14_BRNTAKEN, 9) \ _ELF_DEFINE_RELOC(R_PPC_REL24, 10) \ _ELF_DEFINE_RELOC(R_PPC_REL14, 11) \ _ELF_DEFINE_RELOC(R_PPC_REL14_BRTAKEN, 12) \ _ELF_DEFINE_RELOC(R_PPC_REL14_BRNTAKEN, 13) \ _ELF_DEFINE_RELOC(R_PPC_GOT16, 14) \ _ELF_DEFINE_RELOC(R_PPC_GOT16_LO, 15) \ _ELF_DEFINE_RELOC(R_PPC_GOT16_HI, 16) \ _ELF_DEFINE_RELOC(R_PPC_GOT16_HA, 17) \ _ELF_DEFINE_RELOC(R_PPC_PLTREL24, 18) \ _ELF_DEFINE_RELOC(R_PPC_COPY, 19) \ _ELF_DEFINE_RELOC(R_PPC_GLOB_DAT, 20) \ _ELF_DEFINE_RELOC(R_PPC_JMP_SLOT, 21) \ _ELF_DEFINE_RELOC(R_PPC_RELATIVE, 22) \ _ELF_DEFINE_RELOC(R_PPC_LOCAL24PC, 23) \ _ELF_DEFINE_RELOC(R_PPC_UADDR32, 24) \ _ELF_DEFINE_RELOC(R_PPC_UADDR16, 25) \ _ELF_DEFINE_RELOC(R_PPC_REL32, 26) \ _ELF_DEFINE_RELOC(R_PPC_PLT32, 27) \ _ELF_DEFINE_RELOC(R_PPC_PLTREL32, 28) \ _ELF_DEFINE_RELOC(R_PPC_PLT16_LO, 29) \ _ELF_DEFINE_RELOC(R_PPL_PLT16_HI, 30) \ _ELF_DEFINE_RELOC(R_PPC_PLT16_HA, 31) \ _ELF_DEFINE_RELOC(R_PPC_SDAREL16, 32) \ _ELF_DEFINE_RELOC(R_PPC_SECTOFF, 33) \ _ELF_DEFINE_RELOC(R_PPC_SECTOFF_LO, 34) \ _ELF_DEFINE_RELOC(R_PPC_SECTOFF_HI, 35) \ _ELF_DEFINE_RELOC(R_PPC_SECTOFF_HA, 36) \ _ELF_DEFINE_RELOC(R_PPC_ADDR30, 37) \ _ELF_DEFINE_RELOC(R_PPC_TLS, 67) \ _ELF_DEFINE_RELOC(R_PPC_DTPMOD32, 68) \ _ELF_DEFINE_RELOC(R_PPC_TPREL16, 69) \ _ELF_DEFINE_RELOC(R_PPC_TPREL16_LO, 70) \ _ELF_DEFINE_RELOC(R_PPC_TPREL16_HI, 71) \ _ELF_DEFINE_RELOC(R_PPC_TPREL16_HA, 72) \ _ELF_DEFINE_RELOC(R_PPC_TPREL32, 73) \ _ELF_DEFINE_RELOC(R_PPC_DTPREL16, 74) \ _ELF_DEFINE_RELOC(R_PPC_DTPREL16_LO, 75) \ _ELF_DEFINE_RELOC(R_PPC_DTPREL16_HI, 76) \ _ELF_DEFINE_RELOC(R_PPC_DTPREL16_HA, 77) \ _ELF_DEFINE_RELOC(R_PPC_DTPREL32, 78) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16, 79) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_LO, 80) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_HI, 81) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSGD16_HA, 82) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16, 83) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_LO, 84) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_HI, 85) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TLSLD16_HA, 86) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16, 87) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_LO, 88) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_HI, 89) \ _ELF_DEFINE_RELOC(R_PPC_GOT_TPREL16_HA, 90) \ _ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16, 91) \ _ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_LO, 92) \ _ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_HI, 93) \ _ELF_DEFINE_RELOC(R_PPC_GOT_DTPREL16_HA, 94) \ _ELF_DEFINE_RELOC(R_PPC_TLSGD, 95) \ _ELF_DEFINE_RELOC(R_PPC_TLSLD, 96) \ _ELF_DEFINE_RELOC(R_PPC_EMB_NADDR32, 101) \ _ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16, 102) \ _ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_LO, 103) \ _ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_HI, 104) \ _ELF_DEFINE_RELOC(R_PPC_EMB_NADDR16_HA, 105) \ _ELF_DEFINE_RELOC(R_PPC_EMB_SDAI16, 106) \ _ELF_DEFINE_RELOC(R_PPC_EMB_SDA2I16, 107) \ _ELF_DEFINE_RELOC(R_PPC_EMB_SDA2REL, 108) \ _ELF_DEFINE_RELOC(R_PPC_EMB_SDA21, 109) \ _ELF_DEFINE_RELOC(R_PPC_EMB_MRKREF, 110) \ _ELF_DEFINE_RELOC(R_PPC_EMB_RELSEC16, 111) \ _ELF_DEFINE_RELOC(R_PPC_EMB_RELST_LO, 112) \ _ELF_DEFINE_RELOC(R_PPC_EMB_RELST_HI, 113) \ _ELF_DEFINE_RELOC(R_PPC_EMB_RELST_HA, 114) \ _ELF_DEFINE_RELOC(R_PPC_EMB_BIT_FLD, 115) \ _ELF_DEFINE_RELOC(R_PPC_EMB_RELSDA, 116) \ #define _ELF_DEFINE_PPC64_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_PPC64_NONE, 0) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR32, 1) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR24, 2) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16, 3) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_LO, 4) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HI, 5) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HA, 6) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR14, 7) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR14_BRTAKEN, 8) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR14_BRNTAKEN, 9) \ _ELF_DEFINE_RELOC(R_PPC64_REL24, 10) \ _ELF_DEFINE_RELOC(R_PPC64_REL14, 11) \ _ELF_DEFINE_RELOC(R_PPC64_REL14_BRTAKEN, 12) \ _ELF_DEFINE_RELOC(R_PPC64_REL14_BRNTAKEN, 13) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16, 14) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16_LO, 15) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16_HI, 16) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16_HA, 17) \ _ELF_DEFINE_RELOC(R_PPC64_COPY, 19) \ _ELF_DEFINE_RELOC(R_PPC64_GLOB_DAT, 20) \ _ELF_DEFINE_RELOC(R_PPC64_JMP_SLOT, 21) \ _ELF_DEFINE_RELOC(R_PPC64_RELATIVE, 22) \ _ELF_DEFINE_RELOC(R_PPC64_UADDR32, 24) \ _ELF_DEFINE_RELOC(R_PPC64_UADDR16, 25) \ _ELF_DEFINE_RELOC(R_PPC64_REL32, 26) \ _ELF_DEFINE_RELOC(R_PPC64_PLT32, 27) \ _ELF_DEFINE_RELOC(R_PPC64_PLTREL32, 28) \ _ELF_DEFINE_RELOC(R_PPC64_PLT16_LO, 29) \ _ELF_DEFINE_RELOC(R_PPC64_PLT16_HI, 30) \ _ELF_DEFINE_RELOC(R_PPC64_PLT16_HA, 31) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF, 33) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF_LO, 34) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF_HI, 35) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF_HA, 36) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR30, 37) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR64, 38) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHER, 39) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHERA, 40) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHEST, 41) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_HIGHESTA, 42) \ _ELF_DEFINE_RELOC(R_PPC64_UADDR64, 43) \ _ELF_DEFINE_RELOC(R_PPC64_REL64, 44) \ _ELF_DEFINE_RELOC(R_PPC64_PLT64, 45) \ _ELF_DEFINE_RELOC(R_PPC64_PLTREL64, 46) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16, 47) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16_LO, 48) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16_HI, 49) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16_HA, 50) \ _ELF_DEFINE_RELOC(R_PPC64_TOC, 51) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16, 52) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_LO, 53) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_HI, 54) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_HA, 55) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_DS, 56) \ _ELF_DEFINE_RELOC(R_PPC64_ADDR16_LO_DS, 57) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16_DS, 58) \ _ELF_DEFINE_RELOC(R_PPC64_GOT16_LO_DS, 59) \ _ELF_DEFINE_RELOC(R_PPC64_PLT16_LO_DS, 60) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF_DS, 61) \ _ELF_DEFINE_RELOC(R_PPC64_SECTOFF_LO_DS, 62) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16_DS, 63) \ _ELF_DEFINE_RELOC(R_PPC64_TOC16_LO_DS, 64) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_DS, 65) \ _ELF_DEFINE_RELOC(R_PPC64_PLTGOT16_LO_DS, 66) \ _ELF_DEFINE_RELOC(R_PPC64_TLS, 67) \ _ELF_DEFINE_RELOC(R_PPC64_DTPMOD64, 68) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16, 69) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_LO, 60) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HI, 71) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HA, 72) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL64, 73) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16, 74) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_LO, 75) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HI, 76) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HA, 77) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL64, 78) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16, 79) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_LO, 80) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_HI, 81) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSGD16_HA, 82) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16, 83) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_LO, 84) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_HI, 85) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TLSLD16_HA, 86) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_DS, 87) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_LO_DS, 88) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_HI, 89) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_TPREL16_HA, 90) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_DS, 91) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_LO_DS, 92) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_HI, 93) \ _ELF_DEFINE_RELOC(R_PPC64_GOT_DTPREL16_HA, 94) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_DS, 95) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_LO_DS, 96) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHER, 97) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHERA, 98) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHEST, 99) \ _ELF_DEFINE_RELOC(R_PPC64_TPREL16_HIGHESTA, 100) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_DS, 101) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_LO_DS, 102) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHER, 103) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHERA, 104) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHEST, 105) \ _ELF_DEFINE_RELOC(R_PPC64_DTPREL16_HIGHESTA, 106) \ _ELF_DEFINE_RELOC(R_PPC64_TLSGD, 107) \ _ELF_DEFINE_RELOC(R_PPC64_TLSLD, 108) #define _ELF_DEFINE_SPARC_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_SPARC_NONE, 0) \ _ELF_DEFINE_RELOC(R_SPARC_8, 1) \ _ELF_DEFINE_RELOC(R_SPARC_16, 2) \ _ELF_DEFINE_RELOC(R_SPARC_32, 3) \ _ELF_DEFINE_RELOC(R_SPARC_DISP8, 4) \ _ELF_DEFINE_RELOC(R_SPARC_DISP16, 5) \ _ELF_DEFINE_RELOC(R_SPARC_DISP32, 6) \ _ELF_DEFINE_RELOC(R_SPARC_WDISP30, 7) \ _ELF_DEFINE_RELOC(R_SPARC_WDISP22, 8) \ _ELF_DEFINE_RELOC(R_SPARC_HI22, 9) \ _ELF_DEFINE_RELOC(R_SPARC_22, 10) \ _ELF_DEFINE_RELOC(R_SPARC_13, 11) \ _ELF_DEFINE_RELOC(R_SPARC_LO10, 12) \ _ELF_DEFINE_RELOC(R_SPARC_GOT10, 13) \ _ELF_DEFINE_RELOC(R_SPARC_GOT13, 14) \ _ELF_DEFINE_RELOC(R_SPARC_GOT22, 15) \ _ELF_DEFINE_RELOC(R_SPARC_PC10, 16) \ _ELF_DEFINE_RELOC(R_SPARC_PC22, 17) \ _ELF_DEFINE_RELOC(R_SPARC_WPLT30, 18) \ _ELF_DEFINE_RELOC(R_SPARC_COPY, 19) \ _ELF_DEFINE_RELOC(R_SPARC_GLOB_DAT, 20) \ _ELF_DEFINE_RELOC(R_SPARC_JMP_SLOT, 21) \ _ELF_DEFINE_RELOC(R_SPARC_RELATIVE, 22) \ _ELF_DEFINE_RELOC(R_SPARC_UA32, 23) \ _ELF_DEFINE_RELOC(R_SPARC_PLT32, 24) \ _ELF_DEFINE_RELOC(R_SPARC_HIPLT22, 25) \ _ELF_DEFINE_RELOC(R_SPARC_LOPLT10, 26) \ _ELF_DEFINE_RELOC(R_SPARC_PCPLT32, 27) \ _ELF_DEFINE_RELOC(R_SPARC_PCPLT22, 28) \ _ELF_DEFINE_RELOC(R_SPARC_PCPLT10, 29) \ _ELF_DEFINE_RELOC(R_SPARC_10, 30) \ _ELF_DEFINE_RELOC(R_SPARC_11, 31) \ _ELF_DEFINE_RELOC(R_SPARC_64, 32) \ _ELF_DEFINE_RELOC(R_SPARC_OLO10, 33) \ _ELF_DEFINE_RELOC(R_SPARC_HH22, 34) \ _ELF_DEFINE_RELOC(R_SPARC_HM10, 35) \ _ELF_DEFINE_RELOC(R_SPARC_LM22, 36) \ _ELF_DEFINE_RELOC(R_SPARC_PC_HH22, 37) \ _ELF_DEFINE_RELOC(R_SPARC_PC_HM10, 38) \ _ELF_DEFINE_RELOC(R_SPARC_PC_LM22, 39) \ _ELF_DEFINE_RELOC(R_SPARC_WDISP16, 40) \ _ELF_DEFINE_RELOC(R_SPARC_WDISP19, 41) \ _ELF_DEFINE_RELOC(R_SPARC_7, 43) \ _ELF_DEFINE_RELOC(R_SPARC_5, 44) \ _ELF_DEFINE_RELOC(R_SPARC_6, 45) \ _ELF_DEFINE_RELOC(R_SPARC_DISP64, 46) \ _ELF_DEFINE_RELOC(R_SPARC_PLT64, 47) \ _ELF_DEFINE_RELOC(R_SPARC_HIX22, 48) \ _ELF_DEFINE_RELOC(R_SPARC_LOX10, 49) \ _ELF_DEFINE_RELOC(R_SPARC_H44, 50) \ _ELF_DEFINE_RELOC(R_SPARC_M44, 51) \ _ELF_DEFINE_RELOC(R_SPARC_L44, 52) \ _ELF_DEFINE_RELOC(R_SPARC_REGISTER, 53) \ _ELF_DEFINE_RELOC(R_SPARC_UA64, 54) \ _ELF_DEFINE_RELOC(R_SPARC_UA16, 55) \ _ELF_DEFINE_RELOC(R_SPARC_GOTDATA_HIX22, 80) \ _ELF_DEFINE_RELOC(R_SPARC_GOTDATA_LOX10, 81) \ _ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP_HIX22, 82) \ _ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP_LOX10, 83) \ _ELF_DEFINE_RELOC(R_SPARC_GOTDATA_OP, 84) \ _ELF_DEFINE_RELOC(R_SPARC_H34, 85) #define _ELF_DEFINE_X86_64_RELOCATIONS() \ _ELF_DEFINE_RELOC(R_X86_64_NONE, 0) \ _ELF_DEFINE_RELOC(R_X86_64_64, 1) \ _ELF_DEFINE_RELOC(R_X86_64_PC32, 2) \ _ELF_DEFINE_RELOC(R_X86_64_GOT32, 3) \ _ELF_DEFINE_RELOC(R_X86_64_PLT32, 4) \ _ELF_DEFINE_RELOC(R_X86_64_COPY, 5) \ _ELF_DEFINE_RELOC(R_X86_64_GLOB_DAT, 6) \ _ELF_DEFINE_RELOC(R_X86_64_JUMP_SLOT, 7) \ _ELF_DEFINE_RELOC(R_X86_64_RELATIVE, 8) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPCREL, 9) \ _ELF_DEFINE_RELOC(R_X86_64_32, 10) \ _ELF_DEFINE_RELOC(R_X86_64_32S, 11) \ _ELF_DEFINE_RELOC(R_X86_64_16, 12) \ _ELF_DEFINE_RELOC(R_X86_64_PC16, 13) \ _ELF_DEFINE_RELOC(R_X86_64_8, 14) \ _ELF_DEFINE_RELOC(R_X86_64_PC8, 15) \ _ELF_DEFINE_RELOC(R_X86_64_DTPMOD64, 16) \ _ELF_DEFINE_RELOC(R_X86_64_DTPOFF64, 17) \ _ELF_DEFINE_RELOC(R_X86_64_TPOFF64, 18) \ _ELF_DEFINE_RELOC(R_X86_64_TLSGD, 19) \ _ELF_DEFINE_RELOC(R_X86_64_TLSLD, 20) \ _ELF_DEFINE_RELOC(R_X86_64_DTPOFF32, 21) \ _ELF_DEFINE_RELOC(R_X86_64_GOTTPOFF, 22) \ _ELF_DEFINE_RELOC(R_X86_64_TPOFF32, 23) \ _ELF_DEFINE_RELOC(R_X86_64_PC64, 24) \ _ELF_DEFINE_RELOC(R_X86_64_GOTOFF64, 25) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPC32, 26) \ _ELF_DEFINE_RELOC(R_X86_64_GOT64, 27) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPCREL64, 28) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPC64, 29) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPLT64, 30) \ _ELF_DEFINE_RELOC(R_X86_64_PLTOFF64, 31) \ _ELF_DEFINE_RELOC(R_X86_64_SIZE32, 32) \ _ELF_DEFINE_RELOC(R_X86_64_SIZE64, 33) \ _ELF_DEFINE_RELOC(R_X86_64_GOTPC32_TLSDESC, 34) \ _ELF_DEFINE_RELOC(R_X86_64_TLSDESC_CALL, 35) \ _ELF_DEFINE_RELOC(R_X86_64_TLSDESC, 36) \ _ELF_DEFINE_RELOC(R_X86_64_IRELATIVE, 37) #define _ELF_DEFINE_RELOCATIONS() \ _ELF_DEFINE_386_RELOCATIONS() \ _ELF_DEFINE_AARCH64_RELOCATIONS() \ _ELF_DEFINE_AMD64_RELOCATIONS() \ _ELF_DEFINE_ARM_RELOCATIONS() \ _ELF_DEFINE_IA64_RELOCATIONS() \ _ELF_DEFINE_MIPS_RELOCATIONS() \ _ELF_DEFINE_PPC32_RELOCATIONS() \ _ELF_DEFINE_PPC64_RELOCATIONS() \ _ELF_DEFINE_SPARC_RELOCATIONS() \ _ELF_DEFINE_X86_64_RELOCATIONS() #undef _ELF_DEFINE_RELOC #define _ELF_DEFINE_RELOC(N, V) N = V , enum { _ELF_DEFINE_RELOCATIONS() R__LAST__ }; #define PN_XNUM 0xFFFFU /* Use extended section numbering. */ /** ** ELF Types. **/ typedef uint32_t Elf32_Addr; /* Program address. */ typedef uint8_t Elf32_Byte; /* Unsigned tiny integer. */ typedef uint16_t Elf32_Half; /* Unsigned medium integer. */ typedef uint32_t Elf32_Off; /* File offset. */ typedef uint16_t Elf32_Section; /* Section index. */ typedef int32_t Elf32_Sword; /* Signed integer. */ typedef uint32_t Elf32_Word; /* Unsigned integer. */ typedef uint64_t Elf32_Lword; /* Unsigned long integer. */ typedef uint64_t Elf64_Addr; /* Program address. */ typedef uint8_t Elf64_Byte; /* Unsigned tiny integer. */ typedef uint16_t Elf64_Half; /* Unsigned medium integer. */ typedef uint64_t Elf64_Off; /* File offset. */ typedef uint16_t Elf64_Section; /* Section index. */ typedef int32_t Elf64_Sword; /* Signed integer. */ typedef uint32_t Elf64_Word; /* Unsigned integer. */ typedef uint64_t Elf64_Lword; /* Unsigned long integer. */ typedef uint64_t Elf64_Xword; /* Unsigned long integer. */ typedef int64_t Elf64_Sxword; /* Signed long integer. */ /* * Capability descriptors. */ /* 32-bit capability descriptor. */ typedef struct { Elf32_Word c_tag; /* Type of entry. */ union { Elf32_Word c_val; /* Integer value. */ Elf32_Addr c_ptr; /* Pointer value. */ } c_un; } Elf32_Cap; /* 64-bit capability descriptor. */ typedef struct { Elf64_Xword c_tag; /* Type of entry. */ union { Elf64_Xword c_val; /* Integer value. */ Elf64_Addr c_ptr; /* Pointer value. */ } c_un; } Elf64_Cap; /* * MIPS .conflict section entries. */ /* 32-bit entry. */ typedef struct { Elf32_Addr c_index; } Elf32_Conflict; /* 64-bit entry. */ typedef struct { Elf64_Addr c_index; } Elf64_Conflict; /* * Dynamic section entries. */ /* 32-bit entry. */ typedef struct { Elf32_Sword d_tag; /* Type of entry. */ union { Elf32_Word d_val; /* Integer value. */ Elf32_Addr d_ptr; /* Pointer value. */ } d_un; } Elf32_Dyn; /* 64-bit entry. */ typedef struct { Elf64_Sxword d_tag; /* Type of entry. */ union { Elf64_Xword d_val; /* Integer value. */ Elf64_Addr d_ptr; /* Pointer value; */ } d_un; } Elf64_Dyn; /* * The executable header (EHDR). */ /* 32 bit EHDR. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* ELF identification. */ Elf32_Half e_type; /* Object file type (ET_*). */ Elf32_Half e_machine; /* Machine type (EM_*). */ Elf32_Word e_version; /* File format version (EV_*). */ Elf32_Addr e_entry; /* Start address. */ Elf32_Off e_phoff; /* File offset to the PHDR table. */ Elf32_Off e_shoff; /* File offset to the SHDRheader. */ Elf32_Word e_flags; /* Flags (EF_*). */ Elf32_Half e_ehsize; /* Elf header size in bytes. */ Elf32_Half e_phentsize; /* PHDR table entry size in bytes. */ Elf32_Half e_phnum; /* Number of PHDR entries. */ Elf32_Half e_shentsize; /* SHDR table entry size in bytes. */ Elf32_Half e_shnum; /* Number of SHDR entries. */ Elf32_Half e_shstrndx; /* Index of section name string table. */ } Elf32_Ehdr; /* 64 bit EHDR. */ typedef struct { unsigned char e_ident[EI_NIDENT]; /* ELF identification. */ Elf64_Half e_type; /* Object file type (ET_*). */ Elf64_Half e_machine; /* Machine type (EM_*). */ Elf64_Word e_version; /* File format version (EV_*). */ Elf64_Addr e_entry; /* Start address. */ Elf64_Off e_phoff; /* File offset to the PHDR table. */ Elf64_Off e_shoff; /* File offset to the SHDRheader. */ Elf64_Word e_flags; /* Flags (EF_*). */ Elf64_Half e_ehsize; /* Elf header size in bytes. */ Elf64_Half e_phentsize; /* PHDR table entry size in bytes. */ Elf64_Half e_phnum; /* Number of PHDR entries. */ Elf64_Half e_shentsize; /* SHDR table entry size in bytes. */ Elf64_Half e_shnum; /* Number of SHDR entries. */ Elf64_Half e_shstrndx; /* Index of section name string table. */ } Elf64_Ehdr; /* * Shared object information. */ /* 32-bit entry. */ typedef struct { Elf32_Word l_name; /* The name of a shared object. */ Elf32_Word l_time_stamp; /* 32-bit timestamp. */ Elf32_Word l_checksum; /* Checksum of visible symbols, sizes. */ Elf32_Word l_version; /* Interface version string index. */ Elf32_Word l_flags; /* Flags (LL_*). */ } Elf32_Lib; /* 64-bit entry. */ typedef struct { Elf64_Word l_name; /* The name of a shared object. */ Elf64_Word l_time_stamp; /* 32-bit timestamp. */ Elf64_Word l_checksum; /* Checksum of visible symbols, sizes. */ Elf64_Word l_version; /* Interface version string index. */ Elf64_Word l_flags; /* Flags (LL_*). */ } Elf64_Lib; #define _ELF_DEFINE_LL_FLAGS() \ _ELF_DEFINE_LL(LL_NONE, 0, \ "no flags") \ _ELF_DEFINE_LL(LL_EXACT_MATCH, 0x1, \ "require an exact match") \ _ELF_DEFINE_LL(LL_IGNORE_INT_VER, 0x2, \ "ignore version incompatibilities") \ _ELF_DEFINE_LL(LL_REQUIRE_MINOR, 0x4, \ "") \ _ELF_DEFINE_LL(LL_EXPORTS, 0x8, \ "") \ _ELF_DEFINE_LL(LL_DELAY_LOAD, 0x10, \ "") \ _ELF_DEFINE_LL(LL_DELTA, 0x20, \ "") #undef _ELF_DEFINE_LL #define _ELF_DEFINE_LL(N, V, DESCR) N = V , enum { _ELF_DEFINE_LL_FLAGS() LL__LAST__ }; /* * Note tags */ #define _ELF_DEFINE_NOTE_ENTRY_TYPES() \ _ELF_DEFINE_NT(NT_ABI_TAG, 1, "Tag indicating the ABI") \ _ELF_DEFINE_NT(NT_GNU_HWCAP, 2, "Hardware capabilities") \ _ELF_DEFINE_NT(NT_GNU_BUILD_ID, 3, "Build id, set by ld(1)") \ _ELF_DEFINE_NT(NT_GNU_GOLD_VERSION, 4, \ "Version number of the GNU gold linker") \ _ELF_DEFINE_NT(NT_PRSTATUS, 1, "Process status") \ _ELF_DEFINE_NT(NT_FPREGSET, 2, "Floating point information") \ _ELF_DEFINE_NT(NT_PRPSINFO, 3, "Process information") \ _ELF_DEFINE_NT(NT_AUXV, 6, "Auxiliary vector") \ _ELF_DEFINE_NT(NT_PRXFPREG, 0x46E62B7FUL, \ "Linux user_xfpregs structure") \ _ELF_DEFINE_NT(NT_PSTATUS, 10, "Linux process status") \ _ELF_DEFINE_NT(NT_FPREGS, 12, "Linux floating point regset") \ _ELF_DEFINE_NT(NT_PSINFO, 13, "Linux process information") \ _ELF_DEFINE_NT(NT_LWPSTATUS, 16, "Linux lwpstatus_t type") \ _ELF_DEFINE_NT(NT_LWPSINFO, 17, "Linux lwpinfo_t type") #undef _ELF_DEFINE_NT #define _ELF_DEFINE_NT(N, V, DESCR) N = V , enum { _ELF_DEFINE_NOTE_ENTRY_TYPES() NT__LAST__ }; /* Aliases for the ABI tag. */ #define NT_FREEBSD_ABI_TAG NT_ABI_TAG #define NT_GNU_ABI_TAG NT_ABI_TAG #define NT_NETBSD_IDENT NT_ABI_TAG #define NT_OPENBSD_IDENT NT_ABI_TAG /* * Note descriptors. */ typedef struct { uint32_t n_namesz; /* Length of note's name. */ uint32_t n_descsz; /* Length of note's value. */ uint32_t n_type; /* Type of note. */ } Elf_Note; typedef Elf_Note Elf32_Nhdr; /* 32-bit note header. */ typedef Elf_Note Elf64_Nhdr; /* 64-bit note header. */ /* * MIPS ELF options descriptor header. */ typedef struct { Elf64_Byte kind; /* Type of options. */ Elf64_Byte size; /* Size of option descriptor. */ Elf64_Half section; /* Index of section affected. */ Elf64_Word info; /* Kind-specific information. */ } Elf_Options; /* * Option kinds. */ #define _ELF_DEFINE_OPTION_KINDS() \ _ELF_DEFINE_ODK(ODK_NULL, 0, "undefined") \ _ELF_DEFINE_ODK(ODK_REGINFO, 1, "register usage info") \ _ELF_DEFINE_ODK(ODK_EXCEPTIONS, 2, "exception processing info") \ _ELF_DEFINE_ODK(ODK_PAD, 3, "section padding") \ _ELF_DEFINE_ODK(ODK_HWPATCH, 4, "hardware patch applied") \ _ELF_DEFINE_ODK(ODK_FILL, 5, "fill value used by linker") \ _ELF_DEFINE_ODK(ODK_TAGS, 6, "reserved space for tools") \ _ELF_DEFINE_ODK(ODK_HWAND, 7, "hardware AND patch applied") \ _ELF_DEFINE_ODK(ODK_HWOR, 8, "hardware OR patch applied") \ _ELF_DEFINE_ODK(ODK_GP_GROUP, 9, \ "GP group to use for text/data sections") \ _ELF_DEFINE_ODK(ODK_IDENT, 10, "ID information") \ _ELF_DEFINE_ODK(ODK_PAGESIZE, 11, "page size infomation") #undef _ELF_DEFINE_ODK #define _ELF_DEFINE_ODK(N, V, DESCR) N = V , enum { _ELF_DEFINE_OPTION_KINDS() ODK__LAST__ }; /* * ODK_EXCEPTIONS info field masks. */ #define _ELF_DEFINE_ODK_EXCEPTIONS_MASK() \ _ELF_DEFINE_OEX(OEX_FPU_MIN, 0x0000001FUL, \ "minimum FPU exception which must be enabled") \ _ELF_DEFINE_OEX(OEX_FPU_MAX, 0x00001F00UL, \ "maximum FPU exception which can be enabled") \ _ELF_DEFINE_OEX(OEX_PAGE0, 0x00010000UL, \ "page zero must be mapped") \ _ELF_DEFINE_OEX(OEX_SMM, 0x00020000UL, \ "run in sequential memory mode") \ _ELF_DEFINE_OEX(OEX_PRECISEFP, 0x00040000UL, \ "run in precise FP exception mode") \ _ELF_DEFINE_OEX(OEX_DISMISS, 0x00080000UL, \ "dismiss invalid address traps") #undef _ELF_DEFINE_OEX #define _ELF_DEFINE_OEX(N, V, DESCR) N = V , enum { _ELF_DEFINE_ODK_EXCEPTIONS_MASK() OEX__LAST__ }; /* * ODK_PAD info field masks. */ #define _ELF_DEFINE_ODK_PAD_MASK() \ _ELF_DEFINE_OPAD(OPAD_PREFIX, 0x0001) \ _ELF_DEFINE_OPAD(OPAD_POSTFIX, 0x0002) \ _ELF_DEFINE_OPAD(OPAD_SYMBOL, 0x0004) #undef _ELF_DEFINE_OPAD #define _ELF_DEFINE_OPAD(N, V) N = V , enum { _ELF_DEFINE_ODK_PAD_MASK() OPAD__LAST__ }; /* * ODK_HWPATCH info field masks. */ #define _ELF_DEFINE_ODK_HWPATCH_MASK() \ _ELF_DEFINE_OHW(OHW_R4KEOP, 0x00000001UL, \ "patch for R4000 branch at end-of-page bug") \ _ELF_DEFINE_OHW(OHW_R8KPFETCH, 0x00000002UL, \ "R8000 prefetch bug may occur") \ _ELF_DEFINE_OHW(OHW_R5KEOP, 0x00000004UL, \ "patch for R5000 branch at end-of-page bug") \ _ELF_DEFINE_OHW(OHW_R5KCVTL, 0x00000008UL, \ "R5000 cvt.[ds].l bug: clean == 1") \ _ELF_DEFINE_OHW(OHW_R10KLDL, 0x00000010UL, \ "needd patch for R10000 misaligned load") #undef _ELF_DEFINE_OHW #define _ELF_DEFINE_OHW(N, V, DESCR) N = V , enum { _ELF_DEFINE_ODK_HWPATCH_MASK() OHW__LAST__ }; /* * ODK_HWAND/ODK_HWOR info field and hwp_flags[12] masks. */ #define _ELF_DEFINE_ODK_HWP_MASK() \ _ELF_DEFINE_HWP(OHWA0_R4KEOP_CHECKED, 0x00000001UL, \ "object checked for R4000 end-of-page bug") \ _ELF_DEFINE_HWP(OHWA0_R4KEOP_CLEAN, 0x00000002UL, \ "object verified clean for R4000 end-of-page bug") \ _ELF_DEFINE_HWP(OHWO0_FIXADE, 0x00000001UL, \ "object requires call to fixade") #undef _ELF_DEFINE_HWP #define _ELF_DEFINE_HWP(N, V, DESCR) N = V , enum { _ELF_DEFINE_ODK_HWP_MASK() OHWX0__LAST__ }; /* * ODK_IDENT/ODK_GP_GROUP info field masks. */ #define _ELF_DEFINE_ODK_GP_MASK() \ _ELF_DEFINE_OGP(OGP_GROUP, 0x0000FFFFUL, "GP group number") \ _ELF_DEFINE_OGP(OGP_SELF, 0x00010000UL, \ "GP group is self-contained") #undef _ELF_DEFINE_OGP #define _ELF_DEFINE_OGP(N, V, DESCR) N = V , enum { _ELF_DEFINE_ODK_GP_MASK() OGP__LAST__ }; /* * MIPS ELF register info descriptor. */ /* 32 bit RegInfo entry. */ typedef struct { Elf32_Word ri_gprmask; /* Mask of general register used. */ Elf32_Word ri_cprmask[4]; /* Mask of coprocessor register used. */ Elf32_Addr ri_gp_value; /* GP register value. */ } Elf32_RegInfo; /* 64 bit RegInfo entry. */ typedef struct { Elf64_Word ri_gprmask; /* Mask of general register used. */ Elf64_Word ri_pad; /* Padding. */ Elf64_Word ri_cprmask[4]; /* Mask of coprocessor register used. */ Elf64_Addr ri_gp_value; /* GP register value. */ } Elf64_RegInfo; /* * Program Header Table (PHDR) entries. */ /* 32 bit PHDR entry. */ typedef struct { Elf32_Word p_type; /* Type of segment. */ Elf32_Off p_offset; /* File offset to segment. */ Elf32_Addr p_vaddr; /* Virtual address in memory. */ Elf32_Addr p_paddr; /* Physical address (if relevant). */ Elf32_Word p_filesz; /* Size of segment in file. */ Elf32_Word p_memsz; /* Size of segment in memory. */ Elf32_Word p_flags; /* Segment flags. */ Elf32_Word p_align; /* Alignment constraints. */ } Elf32_Phdr; /* 64 bit PHDR entry. */ typedef struct { Elf64_Word p_type; /* Type of segment. */ Elf64_Word p_flags; /* Segment flags. */ Elf64_Off p_offset; /* File offset to segment. */ Elf64_Addr p_vaddr; /* Virtual address in memory. */ Elf64_Addr p_paddr; /* Physical address (if relevant). */ Elf64_Xword p_filesz; /* Size of segment in file. */ Elf64_Xword p_memsz; /* Size of segment in memory. */ Elf64_Xword p_align; /* Alignment constraints. */ } Elf64_Phdr; /* * Move entries, for describing data in COMMON blocks in a compact * manner. */ /* 32-bit move entry. */ typedef struct { Elf32_Lword m_value; /* Initialization value. */ Elf32_Word m_info; /* Encoded size and index. */ Elf32_Word m_poffset; /* Offset relative to symbol. */ Elf32_Half m_repeat; /* Repeat count. */ Elf32_Half m_stride; /* Number of units to skip. */ } Elf32_Move; /* 64-bit move entry. */ typedef struct { Elf64_Lword m_value; /* Initialization value. */ Elf64_Xword m_info; /* Encoded size and index. */ Elf64_Xword m_poffset; /* Offset relative to symbol. */ Elf64_Half m_repeat; /* Repeat count. */ Elf64_Half m_stride; /* Number of units to skip. */ } Elf64_Move; #define ELF32_M_SYM(I) ((I) >> 8) #define ELF32_M_SIZE(I) ((unsigned char) (I)) #define ELF32_M_INFO(M, S) (((M) << 8) + (unsigned char) (S)) #define ELF64_M_SYM(I) ((I) >> 8) #define ELF64_M_SIZE(I) ((unsigned char) (I)) #define ELF64_M_INFO(M, S) (((M) << 8) + (unsigned char) (S)) /* * Section Header Table (SHDR) entries. */ /* 32 bit SHDR */ typedef struct { Elf32_Word sh_name; /* index of section name */ Elf32_Word sh_type; /* section type */ Elf32_Word sh_flags; /* section flags */ Elf32_Addr sh_addr; /* in-memory address of section */ Elf32_Off sh_offset; /* file offset of section */ Elf32_Word sh_size; /* section size in bytes */ Elf32_Word sh_link; /* section header table link */ Elf32_Word sh_info; /* extra information */ Elf32_Word sh_addralign; /* alignment constraint */ Elf32_Word sh_entsize; /* size for fixed-size entries */ } Elf32_Shdr; /* 64 bit SHDR */ typedef struct { Elf64_Word sh_name; /* index of section name */ Elf64_Word sh_type; /* section type */ Elf64_Xword sh_flags; /* section flags */ Elf64_Addr sh_addr; /* in-memory address of section */ Elf64_Off sh_offset; /* file offset of section */ Elf64_Xword sh_size; /* section size in bytes */ Elf64_Word sh_link; /* section header table link */ Elf64_Word sh_info; /* extra information */ Elf64_Xword sh_addralign; /* alignment constraint */ Elf64_Xword sh_entsize; /* size for fixed-size entries */ } Elf64_Shdr; /* * Symbol table entries. */ typedef struct { Elf32_Word st_name; /* index of symbol's name */ Elf32_Addr st_value; /* value for the symbol */ Elf32_Word st_size; /* size of associated data */ unsigned char st_info; /* type and binding attributes */ unsigned char st_other; /* visibility */ Elf32_Half st_shndx; /* index of related section */ } Elf32_Sym; typedef struct { Elf64_Word st_name; /* index of symbol's name */ unsigned char st_info; /* type and binding attributes */ unsigned char st_other; /* visibility */ Elf64_Half st_shndx; /* index of related section */ Elf64_Addr st_value; /* value for the symbol */ Elf64_Xword st_size; /* size of associated data */ } Elf64_Sym; #define ELF32_ST_BIND(I) ((I) >> 4) #define ELF32_ST_TYPE(I) ((I) & 0xFU) #define ELF32_ST_INFO(B,T) (((B) << 4) + ((T) & 0xF)) #define ELF64_ST_BIND(I) ((I) >> 4) #define ELF64_ST_TYPE(I) ((I) & 0xFU) #define ELF64_ST_INFO(B,T) (((B) << 4) + ((T) & 0xF)) #define ELF32_ST_VISIBILITY(O) ((O) & 0x3) #define ELF64_ST_VISIBILITY(O) ((O) & 0x3) /* * Syminfo descriptors, containing additional symbol information. */ /* 32-bit entry. */ typedef struct { Elf32_Half si_boundto; /* Entry index with additional flags. */ Elf32_Half si_flags; /* Flags. */ } Elf32_Syminfo; /* 64-bit entry. */ typedef struct { Elf64_Half si_boundto; /* Entry index with additional flags. */ Elf64_Half si_flags; /* Flags. */ } Elf64_Syminfo; /* * Relocation descriptors. */ typedef struct { Elf32_Addr r_offset; /* location to apply relocation to */ Elf32_Word r_info; /* type+section for relocation */ } Elf32_Rel; typedef struct { Elf32_Addr r_offset; /* location to apply relocation to */ Elf32_Word r_info; /* type+section for relocation */ Elf32_Sword r_addend; /* constant addend */ } Elf32_Rela; typedef struct { Elf64_Addr r_offset; /* location to apply relocation to */ Elf64_Xword r_info; /* type+section for relocation */ } Elf64_Rel; typedef struct { Elf64_Addr r_offset; /* location to apply relocation to */ Elf64_Xword r_info; /* type+section for relocation */ Elf64_Sxword r_addend; /* constant addend */ } Elf64_Rela; #define ELF32_R_SYM(I) ((I) >> 8) #define ELF32_R_TYPE(I) ((unsigned char) (I)) #define ELF32_R_INFO(S,T) (((S) << 8) + (unsigned char) (T)) #define ELF64_R_SYM(I) ((I) >> 32) #define ELF64_R_TYPE(I) ((I) & 0xFFFFFFFFUL) #define ELF64_R_INFO(S,T) (((S) << 32) + ((T) & 0xFFFFFFFFUL)) /* * Symbol versioning structures. */ /* 32-bit structures. */ typedef struct { Elf32_Word vda_name; /* Index to name. */ Elf32_Word vda_next; /* Offset to next entry. */ } Elf32_Verdaux; typedef struct { Elf32_Word vna_hash; /* Hash value of dependency name. */ Elf32_Half vna_flags; /* Flags. */ Elf32_Half vna_other; /* Unused. */ Elf32_Word vna_name; /* Offset to dependency name. */ Elf32_Word vna_next; /* Offset to next vernaux entry. */ } Elf32_Vernaux; typedef struct { Elf32_Half vd_version; /* Version information. */ Elf32_Half vd_flags; /* Flags. */ Elf32_Half vd_ndx; /* Index into the versym section. */ Elf32_Half vd_cnt; /* Number of aux entries. */ Elf32_Word vd_hash; /* Hash value of name. */ Elf32_Word vd_aux; /* Offset to aux entries. */ Elf32_Word vd_next; /* Offset to next version definition. */ } Elf32_Verdef; typedef struct { Elf32_Half vn_version; /* Version number. */ Elf32_Half vn_cnt; /* Number of aux entries. */ Elf32_Word vn_file; /* Offset of associated file name. */ Elf32_Word vn_aux; /* Offset of vernaux array. */ Elf32_Word vn_next; /* Offset of next verneed entry. */ } Elf32_Verneed; typedef Elf32_Half Elf32_Versym; /* 64-bit structures. */ typedef struct { Elf64_Word vda_name; /* Index to name. */ Elf64_Word vda_next; /* Offset to next entry. */ } Elf64_Verdaux; typedef struct { Elf64_Word vna_hash; /* Hash value of dependency name. */ Elf64_Half vna_flags; /* Flags. */ Elf64_Half vna_other; /* Unused. */ Elf64_Word vna_name; /* Offset to dependency name. */ Elf64_Word vna_next; /* Offset to next vernaux entry. */ } Elf64_Vernaux; typedef struct { Elf64_Half vd_version; /* Version information. */ Elf64_Half vd_flags; /* Flags. */ Elf64_Half vd_ndx; /* Index into the versym section. */ Elf64_Half vd_cnt; /* Number of aux entries. */ Elf64_Word vd_hash; /* Hash value of name. */ Elf64_Word vd_aux; /* Offset to aux entries. */ Elf64_Word vd_next; /* Offset to next version definition. */ } Elf64_Verdef; typedef struct { Elf64_Half vn_version; /* Version number. */ Elf64_Half vn_cnt; /* Number of aux entries. */ Elf64_Word vn_file; /* Offset of associated file name. */ Elf64_Word vn_aux; /* Offset of vernaux array. */ Elf64_Word vn_next; /* Offset of next verneed entry. */ } Elf64_Verneed; typedef Elf64_Half Elf64_Versym; /* * The header for GNU-style hash sections. */ typedef struct { uint32_t gh_nbuckets; /* Number of hash buckets. */ uint32_t gh_symndx; /* First visible symbol in .dynsym. */ uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ uint32_t gh_shift2; /* Bloom filter shift count. */ } Elf_GNU_Hash_Header; #endif /* _ELFDEFINITIONS_H_ */ Index: head/contrib/elftoolchain/common/native-elf-format =================================================================== --- head/contrib/elftoolchain/common/native-elf-format (revision 280931) +++ head/contrib/elftoolchain/common/native-elf-format (revision 280932) @@ -1,47 +1,47 @@ #!/bin/sh # -# $Id: native-elf-format 2064 2011-10-26 15:12:32Z jkoshy $ +# $Id: native-elf-format 3167 2015-02-24 19:10:08Z emaste $ # # Find the native ELF format for a host platform by compiling a # test object and examining the resulting object. # # This script is used if there is no easy way to determine this # information statically at compile time. program=`basename $0` tmp_c=`mktemp -u nefXXXXXX`.c tmp_o=`echo ${tmp_c} | sed -e 's/.c$/.o/'` trap "rm -f ${tmp_c} ${tmp_o}" 0 1 2 3 15 touch ${tmp_c} echo "/* Generated by ${program} on `date` */" cc -c ${tmp_c} -o ${tmp_o} -readelf -h ${tmp_o} | awk ' +LC_ALL=C readelf -h ${tmp_o} | awk ' $1 ~ "Class:" { sub("ELF","",$2); elfclass = $2; } $1 ~ "Data:" { if (match($0, "little")) { elfdata = "LSB"; } else { elfdata = "MSB"; } } $1 ~ "Machine:" { if (match($0, "Intel.*386")) { elfarch = "EM_386"; } else if (match($0, ".*X86-64")) { elfarch = "EM_X86_64"; } else { elfarch = "unknown"; } } END { printf("#define ELFTC_CLASS ELFCLASS%s\n", elfclass); printf("#define ELFTC_ARCH %s\n", elfarch); printf("#define ELFTC_BYTEORDER ELFDATA2%s\n", elfdata); }' Index: head/contrib/elftoolchain/cxxfilt/cxxfilt.c =================================================================== --- head/contrib/elftoolchain/cxxfilt/cxxfilt.c (revision 280931) +++ head/contrib/elftoolchain/cxxfilt/cxxfilt.c (revision 280932) @@ -1,224 +1,223 @@ /*- * Copyright (c) 2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: cxxfilt.c 2185 2011-11-19 16:07:16Z jkoshy $"); +ELFTC_VCSID("$Id: cxxfilt.c 3174 2015-03-27 17:13:41Z emaste $"); #define STRBUFSZ 8192 static int stripus = 0; static int noparam = 0; static int format = 0; enum options { OPTION_HELP, OPTION_VERSION }; static struct option longopts[] = { {"format", required_argument, NULL, 's'}, {"help", no_argument, NULL, OPTION_HELP}, {"no-params", no_argument, NULL, 'p'}, {"no-strip-underscores", no_argument, NULL, 'n'}, {"strip-underscores", no_argument, NULL, '_'}, {"version", no_argument, NULL, 'V'}, {NULL, 0, NULL, 0} }; static struct { const char *fname; int fvalue; } flist[] = { {"auto", 0}, {"arm", ELFTC_DEM_ARM}, {"gnu", ELFTC_DEM_GNU2}, {"gnu-v3", ELFTC_DEM_GNU3} }; #define USAGE_MESSAGE "\ Usage: %s [options] [encoded-names...]\n\ Translate C++ symbol names to human-readable form.\n\n\ Options:\n\ -_ | --strip-underscores Remove leading underscores prior to decoding.\n\ -n | --no-strip-underscores Do not remove leading underscores.\n\ -p | --no-params (Accepted but ignored).\n\ -s SCHEME | --format=SCHEME Select the encoding scheme to use.\n\ Valid schemes are: 'arm', 'auto', 'gnu' and\n\ 'gnu-v3'.\n\ --help Print a help message.\n\ --version Print a version identifier and exit.\n" static void usage(void) { (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(1); } static void version(void) { fprintf(stderr, "%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(0); } static int find_format(const char *fstr) { int i; for (i = 0; (size_t) i < sizeof(flist) / sizeof(flist[0]); i++) { if (!strcmp(fstr, flist[i].fname)) return (flist[i].fvalue); } return (-1); } static char * demangle(char *name, int strict, int *pos) { static char dem[STRBUFSZ]; char nb[STRBUFSZ]; int p, t; if (stripus && *name == '_') { strncpy(nb, name + 1, sizeof(nb) - 1); t = 1; } else { strncpy(nb, name, sizeof(nb) - 1); t = 0; } nb[sizeof(nb) - 1] = '\0'; p = strlen(nb); if (p <= 0) return NULL; while (elftc_demangle(nb, dem, sizeof(dem), format) < 0) { if (!strict && p > 1) { nb[--p] = '\0'; continue; } else return (NULL); } if (pos != NULL) *pos = t ? p + 1 : p; return (dem); } int main(int argc, char **argv) { char *dem, buf[STRBUFSZ]; int c, i, p, s, opt; while ((opt = getopt_long(argc, argv, "_nps:V", longopts, NULL)) != -1) { switch (opt) { case '_': stripus = 1; break; case 'n': stripus = 0; break; case 'p': noparam = 1; break; case 's': if ((format = find_format(optarg)) < 0) errx(EXIT_FAILURE, "unsupported format: %s", optarg); break; case 'V': version(); /* NOT REACHED */ case OPTION_HELP: default: usage(); /* NOT REACHED */ } } argv += optind; argc -= optind; if (*argv != NULL) { for (i = 0; i < argc; i++) { if ((dem = demangle(argv[i], 1, NULL)) == NULL) fprintf(stderr, "Failed: %s\n", argv[i]); else printf("%s\n", dem); } } else { p = 0; for (;;) { c = fgetc(stdin); if (c == EOF || !isprint(c) || strchr(" \t\n", c)) { if (p > 0) { buf[p] = '\0'; if ((dem = demangle(buf, 0, &s)) == NULL) printf("%s", buf); else { printf("%s", dem); for (i = s; i < p; i++) putchar(buf[i]); } p = 0; } if (c == EOF) break; if (isprint(c) || strchr(" \t\n", c)) putchar(c); } else { if ((size_t) p >= sizeof(buf) - 1) warnx("buffer overflowed"); else buf[p++] = c; } } } exit(0); } Index: head/contrib/elftoolchain/elfcopy/archive.c =================================================================== --- head/contrib/elftoolchain/elfcopy/archive.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/archive.c (revision 280932) @@ -1,525 +1,523 @@ /*- * Copyright (c) 2007-2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include #include #ifndef LIBELF_AR #include #include #endif /* ! LIBELF_AR */ #include "elfcopy.h" -ELFTC_VCSID("$Id: archive.c 3102 2014-10-29 21:09:01Z jkoshy $"); +ELFTC_VCSID("$Id: archive.c 3174 2015-03-27 17:13:41Z emaste $"); #define _ARMAG_LEN 8 /* length of ar magic string */ #define _ARHDR_LEN 60 /* length of ar header */ #define _INIT_AS_CAP 128 /* initial archive string table size */ #define _INIT_SYMOFF_CAP (256*(sizeof(uint32_t))) /* initial so table size */ #define _INIT_SYMNAME_CAP 1024 /* initial sn table size */ #define _MAXNAMELEN_SVR4 15 /* max member name length in svr4 variant */ #ifndef LIBELF_AR static void ac_read_objs(struct elfcopy *ecp, int ifd); static void ac_write_cleanup(struct elfcopy *ecp); static void ac_write_data(struct archive *a, const void *buf, size_t s); static void ac_write_objs(struct elfcopy *ecp, int ofd); #endif /* ! LIBELF_AR */ static void add_to_ar_str_table(struct elfcopy *elfcopy, const char *name); static void add_to_ar_sym_table(struct elfcopy *ecp, const char *name); static void extract_arsym(struct elfcopy *ecp); static void process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj); static void sync_ar(struct elfcopy *ecp); static void process_ar_obj(struct elfcopy *ecp, struct ar_obj *obj) { struct stat sb; char *tempfile; int fd; /* Output to a temporary file. */ create_tempfile(&tempfile, &fd); if ((ecp->eout = elf_begin(fd, ELF_C_WRITE, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); create_elf(ecp); elf_end(ecp->ein); elf_end(ecp->eout); free(obj->buf); obj->buf = NULL; /* Extract archive symbols. */ if (lseek(fd, 0, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek failed for '%s'", tempfile); if ((ecp->eout = elf_begin(fd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); extract_arsym(ecp); elf_end(ecp->eout); if (fstat(fd, &sb) == -1) err(EXIT_FAILURE, "fstat %s failed", tempfile); if (lseek(fd, 0, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek %s failed", tempfile); obj->size = sb.st_size; if ((obj->maddr = malloc(obj->size)) == NULL) err(EXIT_FAILURE, "memory allocation failed for '%s'", tempfile); if ((size_t) read(fd, obj->maddr, obj->size) != obj->size) err(EXIT_FAILURE, "read failed for '%s'", tempfile); if (unlink(tempfile)) err(EXIT_FAILURE, "unlink %s failed", tempfile); free(tempfile); close(fd); if (strlen(obj->name) > _MAXNAMELEN_SVR4) add_to_ar_str_table(ecp, obj->name); ecp->rela_off += _ARHDR_LEN + obj->size + obj->size % 2; STAILQ_INSERT_TAIL(&ecp->v_arobj, obj, objs); } /* * Append to the archive string table buffer. */ static void add_to_ar_str_table(struct elfcopy *ecp, const char *name) { if (ecp->as == NULL) { ecp->as_cap = _INIT_AS_CAP; ecp->as_sz = 0; if ((ecp->as = malloc(ecp->as_cap)) == NULL) err(EXIT_FAILURE, "malloc failed"); } /* * The space required for holding one member name in as table includes: * strlen(name) + (1 for '/') + (1 for '\n') + (possibly 1 for padding). */ while (ecp->as_sz + strlen(name) + 3 > ecp->as_cap) { ecp->as_cap *= 2; ecp->as = realloc(ecp->as, ecp->as_cap); if (ecp->as == NULL) err(EXIT_FAILURE, "realloc failed"); } strncpy(&ecp->as[ecp->as_sz], name, strlen(name)); ecp->as_sz += strlen(name); ecp->as[ecp->as_sz++] = '/'; ecp->as[ecp->as_sz++] = '\n'; } /* * Append to the archive symbol table buffer. */ static void add_to_ar_sym_table(struct elfcopy *ecp, const char *name) { if (ecp->s_so == NULL) { if ((ecp->s_so = malloc(_INIT_SYMOFF_CAP)) == NULL) err(EXIT_FAILURE, "malloc failed"); ecp->s_so_cap = _INIT_SYMOFF_CAP; ecp->s_cnt = 0; } if (ecp->s_sn == NULL) { if ((ecp->s_sn = malloc(_INIT_SYMNAME_CAP)) == NULL) err(EXIT_FAILURE, "malloc failed"); ecp->s_sn_cap = _INIT_SYMNAME_CAP; ecp->s_sn_sz = 0; } if (ecp->s_cnt * sizeof(uint32_t) >= ecp->s_so_cap) { ecp->s_so_cap *= 2; ecp->s_so = realloc(ecp->s_so, ecp->s_so_cap); if (ecp->s_so == NULL) err(EXIT_FAILURE, "realloc failed"); } ecp->s_so[ecp->s_cnt] = ecp->rela_off; ecp->s_cnt++; /* * The space required for holding one symbol name in sn table includes: * strlen(name) + (1 for '\n') + (possibly 1 for padding). */ while (ecp->s_sn_sz + strlen(name) + 2 > ecp->s_sn_cap) { ecp->s_sn_cap *= 2; ecp->s_sn = realloc(ecp->s_sn, ecp->s_sn_cap); if (ecp->s_sn == NULL) err(EXIT_FAILURE, "realloc failed"); } strncpy(&ecp->s_sn[ecp->s_sn_sz], name, strlen(name)); ecp->s_sn_sz += strlen(name); ecp->s_sn[ecp->s_sn_sz++] = '\0'; } static void sync_ar(struct elfcopy *ecp) { size_t s_sz; /* size of archive symbol table. */ size_t pm_sz; /* size of pseudo members */ int i; /* * Pad the symbol name string table. It is treated specially because * symbol name table should be padded by a '\0', not the common '\n' * for other members. The size of sn table includes the pad bit. */ if (ecp->s_cnt != 0 && ecp->s_sn_sz % 2 != 0) ecp->s_sn[ecp->s_sn_sz++] = '\0'; /* * Archive string table is padded by a "\n" as the normal members. * The difference is that the size of archive string table counts * in the pad bit, while normal members' size fileds do not. */ if (ecp->as != NULL && ecp->as_sz % 2 != 0) ecp->as[ecp->as_sz++] = '\n'; /* * If there is a symbol table, calculate the size of pseudo members, * convert previously stored relative offsets to absolute ones, and * then make them Big Endian. * * absolute_offset = htobe32(relative_offset + size_of_pseudo_members) */ if (ecp->s_cnt != 0) { s_sz = (ecp->s_cnt + 1) * sizeof(uint32_t) + ecp->s_sn_sz; pm_sz = _ARMAG_LEN + (_ARHDR_LEN + s_sz); if (ecp->as != NULL) pm_sz += _ARHDR_LEN + ecp->as_sz; for (i = 0; (size_t)i < ecp->s_cnt; i++) *(ecp->s_so + i) = htobe32(*(ecp->s_so + i) + pm_sz); } } /* * Extract global symbols from archive members. */ static void extract_arsym(struct elfcopy *ecp) { Elf_Scn *scn; GElf_Shdr shdr; GElf_Sym sym; Elf_Data *data; char *name; size_t n, shstrndx; int elferr, tabndx, len, i; if (elf_kind(ecp->eout) != ELF_K_ELF) { warnx("internal: cannot extract symbols from non-elf object"); return; } if (elf_getshstrndx(ecp->eout, &shstrndx) == 0) { warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); return; } tabndx = -1; scn = NULL; while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != &shdr) { warnx("elf_getshdr failed: %s", elf_errmsg(-1)); continue; } if ((name = elf_strptr(ecp->eout, shstrndx, shdr.sh_name)) == NULL) { warnx("elf_strptr failed: %s", elf_errmsg(-1)); continue; } if (strcmp(name, ".strtab") == 0) { tabndx = elf_ndxscn(scn); break; } } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); /* Ignore members without symbol table. */ if (tabndx == -1) return; scn = NULL; while ((scn = elf_nextscn(ecp->eout, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != &shdr) { warnx("elf_getshdr failed: %s", elf_errmsg(-1)); continue; } if (shdr.sh_type != SHT_SYMTAB) continue; data = NULL; n = 0; while (n < shdr.sh_size && (data = elf_getdata(scn, data)) != NULL) { len = data->d_size / shdr.sh_entsize; for (i = 0; i < len; i++) { if (gelf_getsym(data, i, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; } /* keep only global or weak symbols */ if (GELF_ST_BIND(sym.st_info) != STB_GLOBAL && GELF_ST_BIND(sym.st_info) != STB_WEAK) continue; /* keep only defined symbols */ if (sym.st_shndx == SHN_UNDEF) continue; if ((name = elf_strptr(ecp->eout, tabndx, sym.st_name)) == NULL) { warnx("elf_strptr failed: %s", elf_errmsg(-1)); continue; } add_to_ar_sym_table(ecp, name); } } } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); } #ifndef LIBELF_AR /* * Convenient wrapper for general libarchive error handling. */ #define AC(CALL) do { \ if ((CALL)) \ errx(EXIT_FAILURE, "%s", archive_error_string(a)); \ } while (0) /* Earlier versions of libarchive had some functions that returned 'void'. */ #if ARCHIVE_VERSION_NUMBER >= 2000000 #define ACV(CALL) AC(CALL) #else #define ACV(CALL) do { \ (CALL); \ } while (0) #endif int ac_detect_ar(int ifd) { struct archive *a; struct archive_entry *entry; int r; r = -1; if ((a = archive_read_new()) == NULL) return (0); archive_read_support_format_ar(a); if (archive_read_open_fd(a, ifd, 10240) == ARCHIVE_OK) r = archive_read_next_header(a, &entry); archive_read_close(a); archive_read_free(a); return (r == ARCHIVE_OK); } void ac_create_ar(struct elfcopy *ecp, int ifd, int ofd) { ac_read_objs(ecp, ifd); sync_ar(ecp); ac_write_objs(ecp, ofd); ac_write_cleanup(ecp); } static void ac_read_objs(struct elfcopy *ecp, int ifd) { struct archive *a; struct archive_entry *entry; struct ar_obj *obj; const char *name; char *buff; size_t size; int r; ecp->rela_off = 0; if (lseek(ifd, 0, SEEK_SET) == -1) err(EXIT_FAILURE, "lseek failed"); if ((a = archive_read_new()) == NULL) errx(EXIT_FAILURE, "%s", archive_error_string(a)); archive_read_support_format_ar(a); AC(archive_read_open_fd(a, ifd, 10240)); for(;;) { r = archive_read_next_header(a, &entry); if (r == ARCHIVE_FATAL) errx(EXIT_FAILURE, "%s", archive_error_string(a)); if (r == ARCHIVE_EOF) break; if (r == ARCHIVE_WARN || r == ARCHIVE_RETRY) warnx("%s", archive_error_string(a)); if (r == ARCHIVE_RETRY) continue; name = archive_entry_pathname(entry); /* skip pseudo members. */ if (strcmp(name, "/") == 0 || strcmp(name, "//") == 0) continue; size = archive_entry_size(entry); if (size > 0) { if ((buff = malloc(size)) == NULL) err(EXIT_FAILURE, "malloc failed"); if (archive_read_data(a, buff, size) != (ssize_t)size) { warnx("%s", archive_error_string(a)); free(buff); continue; } if ((obj = malloc(sizeof(*obj))) == NULL) err(EXIT_FAILURE, "malloc failed"); if ((obj->name = strdup(name)) == NULL) err(EXIT_FAILURE, "strdup failed"); obj->buf = buff; obj->uid = archive_entry_uid(entry); obj->gid = archive_entry_gid(entry); obj->md = archive_entry_mode(entry); obj->mtime = archive_entry_mtime(entry); if ((ecp->ein = elf_memory(buff, size)) == NULL) errx(EXIT_FAILURE, "elf_memory() failed: %s", elf_errmsg(-1)); if (elf_kind(ecp->ein) != ELF_K_ELF) errx(EXIT_FAILURE, "file format not recognized"); process_ar_obj(ecp, obj); } } AC(archive_read_close(a)); ACV(archive_read_free(a)); } static void ac_write_objs(struct elfcopy *ecp, int ofd) { struct archive *a; struct archive_entry *entry; struct ar_obj *obj; int nr; if ((a = archive_write_new()) == NULL) errx(EXIT_FAILURE, "%s", archive_error_string(a)); archive_write_set_format_ar_svr4(a); AC(archive_write_open_fd(a, ofd)); /* Write the archive symbol table, even if it's empty. */ entry = archive_entry_new(); archive_entry_copy_pathname(entry, "/"); archive_entry_set_mtime(entry, time(NULL), 0); archive_entry_set_size(entry, (ecp->s_cnt + 1) * sizeof(uint32_t) + ecp->s_sn_sz); AC(archive_write_header(a, entry)); nr = htobe32(ecp->s_cnt); ac_write_data(a, &nr, sizeof(uint32_t)); ac_write_data(a, ecp->s_so, sizeof(uint32_t) * ecp->s_cnt); ac_write_data(a, ecp->s_sn, ecp->s_sn_sz); archive_entry_free(entry); /* Write the archive string table, if exist. */ if (ecp->as != NULL) { entry = archive_entry_new(); archive_entry_copy_pathname(entry, "//"); archive_entry_set_size(entry, ecp->as_sz); AC(archive_write_header(a, entry)); ac_write_data(a, ecp->as, ecp->as_sz); archive_entry_free(entry); } /* Write normal members. */ STAILQ_FOREACH(obj, &ecp->v_arobj, objs) { entry = archive_entry_new(); archive_entry_copy_pathname(entry, obj->name); archive_entry_set_uid(entry, obj->uid); archive_entry_set_gid(entry, obj->gid); archive_entry_set_mode(entry, obj->md); archive_entry_set_size(entry, obj->size); archive_entry_set_mtime(entry, obj->mtime, 0); archive_entry_set_filetype(entry, AE_IFREG); AC(archive_write_header(a, entry)); ac_write_data(a, obj->maddr, obj->size); archive_entry_free(entry); } AC(archive_write_close(a)); ACV(archive_write_free(a)); } static void ac_write_cleanup(struct elfcopy *ecp) { struct ar_obj *obj, *obj_temp; STAILQ_FOREACH_SAFE(obj, &ecp->v_arobj, objs, obj_temp) { STAILQ_REMOVE(&ecp->v_arobj, obj, ar_obj, objs); if (obj->maddr != NULL) free(obj->maddr); free(obj->name); free(obj); } free(ecp->as); free(ecp->s_so); free(ecp->s_sn); ecp->as = NULL; ecp->s_so = NULL; ecp->s_sn = NULL; } /* * Wrapper for archive_write_data(). */ static void ac_write_data(struct archive *a, const void *buf, size_t s) { if (archive_write_data(a, buf, s) != (ssize_t)s) errx(EXIT_FAILURE, "%s", archive_error_string(a)); } #endif /* ! LIBELF_AR */ Index: head/contrib/elftoolchain/elfcopy/ascii.c =================================================================== --- head/contrib/elftoolchain/elfcopy/ascii.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/ascii.c (revision 280932) @@ -1,1079 +1,1078 @@ /*- * Copyright (c) 2010,2011 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: ascii.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); +ELFTC_VCSID("$Id: ascii.c 3177 2015-03-30 18:19:41Z emaste $"); static void append_data(struct section *s, const void *buf, size_t sz); static char hex_digit(uint8_t n); static int hex_value(int x); static void finalize_data_section(struct section *s); static int ishexdigit(int x); static int ihex_read(const char *line, char *type, uint64_t *addr, uint64_t *num, uint8_t *data, size_t *sz); static void ihex_write(int ofd, int type, uint64_t addr, uint64_t num, const void *buf, size_t sz); static void ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz); static void ihex_write_01(int ofd); static void ihex_write_04(int ofd, uint16_t addr); static void ihex_write_05(int ofd, uint64_t e_entry); static struct section *new_data_section(struct elfcopy *ecp, int sec_index, uint64_t off, uint64_t addr); static int read_num(const char *line, int *len, uint64_t *num, size_t sz, int *checksum); static int srec_read(const char *line, char *type, uint64_t *addr, uint8_t *data, size_t *sz); static void srec_write(int ofd, char type, uint64_t addr, const void *buf, size_t sz); static void srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn, GElf_Shdr *sh); static void srec_write_S0(int ofd, const char *ofn); static void srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf, size_t sz, size_t rlen); static void srec_write_Se(int ofd, uint64_t e_entry, int forceS3); static void write_num(char *line, int *len, uint64_t num, size_t sz, int *checksum); #define _LINE_BUFSZ 1024 #define _DATA_BUFSZ 256 /* * Convert ELF object to S-Record. */ void create_srec(struct elfcopy *ecp, int ifd, int ofd, const char *ofn) { Elf *e; Elf_Scn *scn; Elf_Data *d; GElf_Ehdr eh; GElf_Shdr sh; uint64_t max_addr; size_t rlen; int elferr, addr_sz; char dr; if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); /* Output a symbol table for `symbolsrec' target. */ if (!strncmp(ecp->otgt, "symbolsrec", strlen("symbolsrec"))) { scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if (sh.sh_type != SHT_SYMTAB) continue; srec_write_symtab(ofd, ofn, e, scn, &sh); break; } } if (ecp->flags & SREC_FORCE_S3) dr = '3'; else { /* * Find maximum address size in the first iteration. */ max_addr = 0; scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((sh.sh_flags & SHF_ALLOC) == 0 || sh.sh_type == SHT_NOBITS || sh.sh_size == 0) continue; if ((uint64_t) sh.sh_addr > max_addr) max_addr = sh.sh_addr; } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); if (max_addr <= 0xFFFF) dr = '1'; else if (max_addr <= 0xFFFFFF) dr = '2'; else dr = '3'; } if (ecp->flags & SREC_FORCE_LEN) { addr_sz = dr - '0' + 1; if (ecp->srec_len < 1) rlen = 1; else if (ecp->srec_len + addr_sz + 1 > 255) rlen = 255 - (addr_sz + 1); else rlen = ecp->srec_len; } else rlen = 16; /* Generate S0 record which contains the output filename. */ srec_write_S0(ofd, ofn); /* Generate S{1,2,3} data records for section data. */ scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((sh.sh_flags & SHF_ALLOC) == 0 || sh.sh_type == SHT_NOBITS || sh.sh_size == 0) continue; if (sh.sh_addr > 0xFFFFFFFF) { warnx("address space too big for S-Record file"); continue; } (void) elf_errno(); if ((d = elf_getdata(scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); continue; } if (d->d_buf == NULL || d->d_size == 0) continue; srec_write_Sd(ofd, dr, sh.sh_addr, d->d_buf, d->d_size, rlen); } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); /* Generate S{7,8,9} end of block recrod. */ if (gelf_getehdr(e, &eh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); srec_write_Se(ofd, eh.e_entry, ecp->flags & SREC_FORCE_S3); } void create_elf_from_srec(struct elfcopy *ecp, int ifd) { char line[_LINE_BUFSZ], name[_LINE_BUFSZ]; uint8_t data[_DATA_BUFSZ]; GElf_Ehdr oeh; struct section *s, *shtab; FILE *ifp; uint64_t addr, entry, off, sec_addr; uintmax_t st_value; size_t sz; int _ifd, first, sec_index, in_symtab, symtab_created; char *rlt; char type; if ((_ifd = dup(ifd)) < 0) err(EXIT_FAILURE, "dup failed"); if ((ifp = fdopen(_ifd, "r")) == NULL) err(EXIT_FAILURE, "fdopen failed"); /* Create EHDR for output .o file. */ if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) errx(EXIT_FAILURE, "gelf_newehdr failed: %s", elf_errmsg(-1)); if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Initialise e_ident fields. */ oeh.e_ident[EI_CLASS] = ecp->oec; oeh.e_ident[EI_DATA] = ecp->oed; /* * TODO: Set OSABI according to the OS platform where elfcopy(1) * was build. (probably) */ oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; oeh.e_machine = ecp->oem; oeh.e_type = ET_REL; oeh.e_entry = 0; ecp->flags |= RELOCATABLE; /* Create .shstrtab section */ init_shstrtab(ecp); ecp->shstrtab->off = 0; /* Data sections are inserted after EHDR. */ off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); if (off == 0) errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); /* Create data sections. */ s = NULL; first = 1; sec_index = 1; sec_addr = entry = 0; while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { if (line[0] == '\r' || line[0] == '\n') continue; if (line[0] == '$' && line[1] == '$') { ecp->flags |= SYMTAB_EXIST; while ((rlt = fgets(line, _LINE_BUFSZ, ifp)) != NULL) { if (line[0] == '$' && line[1] == '$') break; } if (rlt == NULL) break; continue; } if (line[0] != 'S' || line[1] < '0' || line[1] > '9') { warnx("Invalid srec record"); continue; } if (srec_read(line, &type, &addr, data, &sz) < 0) { warnx("Invalid srec record or mismatched checksum"); continue; } switch (type) { case '1': case '2': case '3': if (sz == 0) break; if (first || sec_addr != addr) { if (s != NULL) finalize_data_section(s); s = new_data_section(ecp, sec_index, off, addr); if (s == NULL) { warnx("new_data_section failed"); break; } sec_index++; sec_addr = addr; first = 0; } append_data(s, data, sz); off += sz; sec_addr += sz; break; case '7': case '8': case '9': entry = addr; break; default: break; } } if (s != NULL) finalize_data_section(s); if (ferror(ifp)) warn("fgets failed"); /* Insert .shstrtab after data sections. */ if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn failed: %s", elf_errmsg(-1)); insert_to_sec_list(ecp, ecp->shstrtab, 1); /* Insert section header table here. */ shtab = insert_shtab(ecp, 1); /* * Rescan and create symbol table if we found '$$' section in * the first scan. */ symtab_created = 0; in_symtab = 0; if (ecp->flags & SYMTAB_EXIST) { if (fseek(ifp, 0, SEEK_SET) < 0) { warn("fseek failed"); ecp->flags &= ~SYMTAB_EXIST; goto done; } while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { if (in_symtab) { if (line[0] == '$' && line[1] == '$') { in_symtab = 0; continue; } if (sscanf(line, "%s $%jx", name, &st_value) != 2) { warnx("Invalid symbolsrec record"); continue; } if (!symtab_created) { create_external_symtab(ecp); symtab_created = 1; } add_to_symtab(ecp, name, st_value, 0, SHN_ABS, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); } if (line[0] == '$' && line[1] == '$') { in_symtab = 1; continue; } } } if (ferror(ifp)) warn("fgets failed"); if (symtab_created) { finalize_external_symtab(ecp); create_symtab_data(ecp); /* Count in .symtab and .strtab section headers. */ shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT); } else ecp->flags &= ~SYMTAB_EXIST; done: fclose(ifp); /* Set entry point. */ oeh.e_entry = entry; /* * Write the underlying ehdr. Note that it should be called * before elf_setshstrndx() since it will overwrite e->e_shstrndx. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Generate section name string table (.shstrtab). */ set_shstrtab(ecp); /* Update sh_name pointer for each section header entry. */ update_shdr(ecp, 0); /* Renew oeh to get the updated e_shstrndx. */ if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Resync section offsets. */ resync_sections(ecp); /* Store SHDR offset in EHDR. */ oeh.e_shoff = shtab->off; /* Update ehdr since we modified e_shoff. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Write out the output elf object. */ if (elf_update(ecp->eout, ELF_C_WRITE) < 0) errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); /* Release allocated resource. */ free_elf(ecp); } void create_ihex(int ifd, int ofd) { Elf *e; Elf_Scn *scn; Elf_Data *d; GElf_Ehdr eh; GElf_Shdr sh; int elferr; uint16_t addr_hi, old_addr_hi; if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); old_addr_hi = 0; scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((sh.sh_flags & SHF_ALLOC) == 0 || sh.sh_type == SHT_NOBITS || sh.sh_size == 0) continue; if (sh.sh_addr > 0xFFFFFFFF) { warnx("address space too big for Intel Hex file"); continue; } (void) elf_errno(); if ((d = elf_getdata(scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); continue; } if (d->d_buf == NULL || d->d_size == 0) continue; addr_hi = (sh.sh_addr >> 16) & 0xFFFF; if (addr_hi > 0 && addr_hi != old_addr_hi) { /* Write 04 record if addr_hi is new. */ old_addr_hi = addr_hi; ihex_write_04(ofd, addr_hi); } ihex_write_00(ofd, sh.sh_addr, d->d_buf, d->d_size); } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); if (gelf_getehdr(e, &eh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); ihex_write_05(ofd, eh.e_entry); ihex_write_01(ofd); } void create_elf_from_ihex(struct elfcopy *ecp, int ifd) { char line[_LINE_BUFSZ]; uint8_t data[_DATA_BUFSZ]; GElf_Ehdr oeh; struct section *s, *shtab; FILE *ifp; uint64_t addr, addr_base, entry, num, off, rec_addr, sec_addr; size_t sz; int _ifd, first, sec_index; char type; if ((_ifd = dup(ifd)) < 0) err(EXIT_FAILURE, "dup failed"); if ((ifp = fdopen(_ifd, "r")) == NULL) err(EXIT_FAILURE, "fdopen failed"); /* Create EHDR for output .o file. */ if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) errx(EXIT_FAILURE, "gelf_newehdr failed: %s", elf_errmsg(-1)); if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Initialise e_ident fields. */ oeh.e_ident[EI_CLASS] = ecp->oec; oeh.e_ident[EI_DATA] = ecp->oed; /* * TODO: Set OSABI according to the OS platform where elfcopy(1) * was build. (probably) */ oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; oeh.e_machine = ecp->oem; oeh.e_type = ET_REL; oeh.e_entry = 0; ecp->flags |= RELOCATABLE; /* Create .shstrtab section */ init_shstrtab(ecp); ecp->shstrtab->off = 0; /* Data sections are inserted after EHDR. */ off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); if (off == 0) errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); /* Create data sections. */ s = NULL; first = 1; sec_index = 1; addr_base = rec_addr = sec_addr = entry = 0; while (fgets(line, _LINE_BUFSZ, ifp) != NULL) { if (line[0] == '\r' || line[0] == '\n') continue; if (line[0] != ':') { warnx("Invalid ihex record"); continue; } if (ihex_read(line, &type, &addr, &num, data, &sz) < 0) { warnx("Invalid ihex record or mismatched checksum"); continue; } switch (type) { case '0': /* Data record. */ if (sz == 0) break; rec_addr = addr_base + addr; if (first || sec_addr != rec_addr) { if (s != NULL) finalize_data_section(s); s = new_data_section(ecp, sec_index, off, rec_addr); if (s == NULL) { warnx("new_data_section failed"); break; } sec_index++; sec_addr = rec_addr; first = 0; } append_data(s, data, sz); off += sz; sec_addr += sz; break; case '1': /* End of file record. */ goto done; case '2': /* Extended segment address record. */ addr_base = addr << 4; break; case '3': /* Start segment address record (CS:IP). Ignored. */ break; case '4': /* Extended linear address record. */ addr_base = num << 16; break; case '5': /* Start linear address record. */ entry = num; break; default: break; } } done: if (s != NULL) finalize_data_section(s); if (ferror(ifp)) warn("fgets failed"); fclose(ifp); /* Insert .shstrtab after data sections. */ if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn failed: %s", elf_errmsg(-1)); insert_to_sec_list(ecp, ecp->shstrtab, 1); /* Insert section header table here. */ shtab = insert_shtab(ecp, 1); /* Set entry point. */ oeh.e_entry = entry; /* * Write the underlying ehdr. Note that it should be called * before elf_setshstrndx() since it will overwrite e->e_shstrndx. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Generate section name string table (.shstrtab). */ set_shstrtab(ecp); /* Update sh_name pointer for each section header entry. */ update_shdr(ecp, 0); /* Renew oeh to get the updated e_shstrndx. */ if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Resync section offsets. */ resync_sections(ecp); /* Store SHDR offset in EHDR. */ oeh.e_shoff = shtab->off; /* Update ehdr since we modified e_shoff. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Write out the output elf object. */ if (elf_update(ecp->eout, ELF_C_WRITE) < 0) errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); /* Release allocated resource. */ free_elf(ecp); } #define _SEC_NAMESZ 64 #define _SEC_INIT_CAP 1024 static struct section * new_data_section(struct elfcopy *ecp, int sec_index, uint64_t off, uint64_t addr) { char *name; if ((name = malloc(_SEC_NAMESZ)) == NULL) errx(EXIT_FAILURE, "malloc failed"); snprintf(name, _SEC_NAMESZ, ".sec%d", sec_index); return (create_external_section(ecp, name, name, NULL, 0, off, SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, addr, 0)); } static void finalize_data_section(struct section *s) { Elf_Data *od; if ((od = elf_newdata(s->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s", elf_errmsg(-1)); od->d_align = s->align; od->d_off = 0; od->d_buf = s->buf; od->d_size = s->sz; od->d_version = EV_CURRENT; } static void append_data(struct section *s, const void *buf, size_t sz) { uint8_t *p; if (s->buf == NULL) { s->sz = 0; s->cap = _SEC_INIT_CAP; if ((s->buf = malloc(s->cap)) == NULL) err(EXIT_FAILURE, "malloc failed"); } while (sz + s->sz > s->cap) { s->cap *= 2; if ((s->buf = realloc(s->buf, s->cap)) == NULL) err(EXIT_FAILURE, "realloc failed"); } p = s->buf; memcpy(&p[s->sz], buf, sz); s->sz += sz; } static int srec_read(const char *line, char *type, uint64_t *addr, uint8_t *data, size_t *sz) { uint64_t count, _checksum, num; size_t addr_sz; int checksum, i, len; checksum = 0; len = 2; if (read_num(line, &len, &count, 1, &checksum) < 0) return (-1); *type = line[1]; switch (*type) { case '0': case '1': case '5': case '9': addr_sz = 2; break; case '2': case '8': addr_sz = 3; break; case '3': case '7': addr_sz = 4; break; default: return (-1); } if (read_num(line, &len, addr, addr_sz, &checksum) < 0) return (-1); count -= addr_sz + 1; if (*type >= '0' && *type <= '3') { for (i = 0; (uint64_t) i < count; i++) { if (read_num(line, &len, &num, 1, &checksum) < 0) return -1; data[i] = (uint8_t) num; } *sz = count; } else *sz = 0; if (read_num(line, &len, &_checksum, 1, NULL) < 0) return (-1); if ((int) _checksum != (~checksum & 0xFF)) return (-1); return (0); } static void srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn, GElf_Shdr *sh) { char line[_LINE_BUFSZ]; GElf_Sym sym; Elf_Data *d; const char *name; size_t sc; int elferr, i; #define _WRITE_LINE do { \ if (write(ofd, line, strlen(line)) != (ssize_t) strlen(line)) \ errx(EXIT_FAILURE, "write failed"); \ } while (0) (void) elf_errno(); if ((d = elf_getdata(scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_buf == NULL || d->d_size == 0) return; snprintf(line, sizeof(line), "$$ %s\r\n", ofn); _WRITE_LINE; sc = d->d_size / sh->sh_entsize; for (i = 1; (size_t) i < sc; i++) { if (gelf_getsym(d, i, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; } if (GELF_ST_TYPE(sym.st_info) == STT_SECTION || GELF_ST_TYPE(sym.st_info) == STT_FILE) continue; if ((name = elf_strptr(e, sh->sh_link, sym.st_name)) == NULL) { warnx("elf_strptr failed: %s", elf_errmsg(-1)); continue; } snprintf(line, sizeof(line), " %s $%jx\r\n", name, (uintmax_t) sym.st_value); _WRITE_LINE; } snprintf(line, sizeof(line), "$$ \r\n"); _WRITE_LINE; #undef _WRITE_LINE } static void srec_write_S0(int ofd, const char *ofn) { srec_write(ofd, '0', 0, ofn, strlen(ofn)); } static void srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf, size_t sz, size_t rlen) { const uint8_t *p, *pe; p = buf; pe = p + sz; while (pe - p >= (int) rlen) { srec_write(ofd, dr, addr, p, rlen); addr += rlen; p += rlen; } if (pe - p > 0) srec_write(ofd, dr, addr, p, pe - p); } static void srec_write_Se(int ofd, uint64_t e_entry, int forceS3) { char er; if (e_entry > 0xFFFFFFFF) { warnx("address space too big for S-Record file"); return; } if (forceS3) er = '7'; else { if (e_entry <= 0xFFFF) er = '9'; else if (e_entry <= 0xFFFFFF) er = '8'; else er = '7'; } srec_write(ofd, er, e_entry, NULL, 0); } static void srec_write(int ofd, char type, uint64_t addr, const void *buf, size_t sz) { char line[_LINE_BUFSZ]; const uint8_t *p, *pe; int len, addr_sz, checksum; if (type == '0' || type == '1' || type == '5' || type == '9') addr_sz = 2; else if (type == '2' || type == '8') addr_sz = 3; else addr_sz = 4; checksum = 0; line[0] = 'S'; line[1] = type; len = 2; write_num(line, &len, addr_sz + sz + 1, 1, &checksum); write_num(line, &len, addr, addr_sz, &checksum); for (p = buf, pe = p + sz; p < pe; p++) write_num(line, &len, *p, 1, &checksum); write_num(line, &len, ~checksum & 0xFF, 1, NULL); line[len++] = '\r'; line[len++] = '\n'; if (write(ofd, line, len) != (ssize_t) len) err(EXIT_FAILURE, "write failed"); } static void ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz) { uint16_t addr_hi, old_addr_hi; const uint8_t *p, *pe; old_addr_hi = (addr >> 16) & 0xFFFF; p = buf; pe = p + sz; while (pe - p >= 16) { ihex_write(ofd, 0, addr, 0, p, 16); addr += 16; p += 16; addr_hi = (addr >> 16) & 0xFFFF; if (addr_hi != old_addr_hi) { old_addr_hi = addr_hi; ihex_write_04(ofd, addr_hi); } } if (pe - p > 0) ihex_write(ofd, 0, addr, 0, p, pe - p); } static int ihex_read(const char *line, char *type, uint64_t *addr, uint64_t *num, uint8_t *data, size_t *sz) { uint64_t count, _checksum; int checksum, i, len; *sz = 0; checksum = 0; len = 1; if (read_num(line, &len, &count, 1, &checksum) < 0) return (-1); if (read_num(line, &len, addr, 2, &checksum) < 0) return (-1); if (line[len++] != '0') return (-1); *type = line[len++]; checksum += *type - '0'; switch (*type) { case '0': for (i = 0; (uint64_t) i < count; i++) { if (read_num(line, &len, num, 1, &checksum) < 0) return (-1); data[i] = (uint8_t) *num; } *sz = count; break; case '1': if (count != 0) return (-1); break; case '2': case '4': if (count != 2) return (-1); if (read_num(line, &len, num, 2, &checksum) < 0) return (-1); break; case '3': case '5': if (count != 4) return (-1); if (read_num(line, &len, num, 4, &checksum) < 0) return (-1); break; default: return (-1); } if (read_num(line, &len, &_checksum, 1, &checksum) < 0) return (-1); if ((checksum & 0xFF) != 0) { return (-1); } return (0); } static void ihex_write_01(int ofd) { ihex_write(ofd, 1, 0, 0, NULL, 0); } static void ihex_write_04(int ofd, uint16_t addr) { ihex_write(ofd, 4, 0, addr, NULL, 2); } static void ihex_write_05(int ofd, uint64_t e_entry) { if (e_entry > 0xFFFFFFFF) { warnx("address space too big for Intel Hex file"); return; } ihex_write(ofd, 5, 0, e_entry, NULL, 4); } static void ihex_write(int ofd, int type, uint64_t addr, uint64_t num, const void *buf, size_t sz) { char line[_LINE_BUFSZ]; const uint8_t *p, *pe; int len, checksum; if (sz > 16) errx(EXIT_FAILURE, "Internal: ihex_write() sz too big"); checksum = 0; line[0] = ':'; len = 1; write_num(line, &len, sz, 1, &checksum); write_num(line, &len, addr, 2, &checksum); write_num(line, &len, type, 1, &checksum); if (sz > 0) { if (buf != NULL) { for (p = buf, pe = p + sz; p < pe; p++) write_num(line, &len, *p, 1, &checksum); } else write_num(line, &len, num, sz, &checksum); } write_num(line, &len, (~checksum + 1) & 0xFF, 1, NULL); line[len++] = '\r'; line[len++] = '\n'; if (write(ofd, line, len) != (ssize_t) len) err(EXIT_FAILURE, "write failed"); } static int read_num(const char *line, int *len, uint64_t *num, size_t sz, int *checksum) { uint8_t b; *num = 0; for (; sz > 0; sz--) { if (!ishexdigit(line[*len]) || !ishexdigit(line[*len + 1])) return (-1); b = (hex_value(line[*len]) << 4) | hex_value(line[*len + 1]); *num = (*num << 8) | b; *len += 2; if (checksum != NULL) *checksum = (*checksum + b) & 0xFF; } return (0); } static void write_num(char *line, int *len, uint64_t num, size_t sz, int *checksum) { uint8_t b; for (; sz > 0; sz--) { b = (num >> ((sz - 1) * 8)) & 0xFF; line[*len] = hex_digit((b >> 4) & 0xF); line[*len + 1] = hex_digit(b & 0xF); *len += 2; if (checksum != NULL) *checksum = (*checksum + b) & 0xFF; } } static char hex_digit(uint8_t n) { return ((n < 10) ? '0' + n : 'A' + (n - 10)); } static int hex_value(int x) { if (isdigit(x)) return (x - '0'); else if (x >= 'a' && x <= 'f') return (x - 'a' + 10); else return (x - 'A' + 10); } static int ishexdigit(int x) { if (isdigit(x)) return (1); if ((x >= 'a' && x <= 'f') || (x >= 'A' && x <= 'F')) return (1); return (0); } Index: head/contrib/elftoolchain/elfcopy/binary.c =================================================================== --- head/contrib/elftoolchain/elfcopy/binary.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/binary.c (revision 280932) @@ -1,286 +1,285 @@ /*- * Copyright (c) 2010,2011 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: binary.c 2358 2011-12-19 18:22:32Z kaiwang27 $"); +ELFTC_VCSID("$Id: binary.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Convert ELF object to `binary'. Sections with SHF_ALLOC flag set * are copied to the result binary. The relative offsets for each section * are retained, so the result binary file might contain "holes". */ void create_binary(int ifd, int ofd) { Elf *e; Elf_Scn *scn; Elf_Data *d; GElf_Shdr sh; off_t base, off; int elferr; if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); base = 0; if (lseek(ofd, base, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek failed"); /* * Find base offset in the first iteration. */ base = -1; scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((sh.sh_flags & SHF_ALLOC) == 0 || sh.sh_type == SHT_NOBITS || sh.sh_size == 0) continue; if (base == -1 || (off_t) sh.sh_offset < base) base = sh.sh_offset; } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); if (base == -1) return; /* * Write out sections in the second iteration. */ scn = NULL; while ((scn = elf_nextscn(e, scn)) != NULL) { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((sh.sh_flags & SHF_ALLOC) == 0 || sh.sh_type == SHT_NOBITS || sh.sh_size == 0) continue; (void) elf_errno(); if ((d = elf_getdata(scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); continue; } if (d->d_buf == NULL || d->d_size == 0) continue; /* lseek to section offset relative to `base'. */ off = sh.sh_offset - base; if (lseek(ofd, off, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek failed"); /* Write out section contents. */ if (write(ofd, d->d_buf, d->d_size) != (ssize_t) d->d_size) err(EXIT_FAILURE, "write failed"); } elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); } #define _SYMBOL_NAMSZ 1024 /* * Convert `binary' to ELF object. The input `binary' is converted to * a relocatable (.o) file, a few symbols will also be created to make * it easier to access the binary data in other compilation units. */ void create_elf_from_binary(struct elfcopy *ecp, int ifd, const char *ifn) { char name[_SYMBOL_NAMSZ]; struct section *sec, *sec_temp, *shtab; struct stat sb; GElf_Ehdr oeh; GElf_Shdr sh; void *content; uint64_t off, data_start, data_end, data_size; /* Reset internal section list. */ if (!TAILQ_EMPTY(&ecp->v_sec)) TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) { TAILQ_REMOVE(&ecp->v_sec, sec, sec_list); free(sec); } if (fstat(ifd, &sb) == -1) err(EXIT_FAILURE, "fstat failed"); /* Read the input binary file to a internal buffer. */ if ((content = malloc(sb.st_size)) == NULL) err(EXIT_FAILURE, "malloc failed"); if (read(ifd, content, sb.st_size) != sb.st_size) err(EXIT_FAILURE, "read failed"); /* * TODO: copy the input binary to output binary verbatim if -O is not * specified. */ /* Create EHDR for output .o file. */ if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) errx(EXIT_FAILURE, "gelf_newehdr failed: %s", elf_errmsg(-1)); if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Initialise e_ident fields. */ oeh.e_ident[EI_CLASS] = ecp->oec; oeh.e_ident[EI_DATA] = ecp->oed; /* * TODO: Set OSABI according to the OS platform where elfcopy(1) * was build. (probably) */ oeh.e_ident[EI_OSABI] = ELFOSABI_NONE; oeh.e_machine = ecp->oem; oeh.e_type = ET_REL; oeh.e_entry = 0; ecp->flags |= RELOCATABLE; /* Create .shstrtab section */ init_shstrtab(ecp); ecp->shstrtab->off = 0; /* * Create `.data' section which contains the binary data. The * section is inserted immediately after EHDR. */ off = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); if (off == 0) errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); (void) create_external_section(ecp, ".data", NULL, content, sb.st_size, off, SHT_PROGBITS, ELF_T_BYTE, SHF_ALLOC | SHF_WRITE, 1, 0, 1); /* Insert .shstrtab after .data section. */ if ((ecp->shstrtab->os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn failed: %s", elf_errmsg(-1)); insert_to_sec_list(ecp, ecp->shstrtab, 1); /* Insert section header table here. */ shtab = insert_shtab(ecp, 1); /* Count in .symtab and .strtab section headers. */ shtab->sz += gelf_fsize(ecp->eout, ELF_T_SHDR, 2, EV_CURRENT); #define _GEN_SYMNAME(S) do { \ snprintf(name, sizeof(name), "%s%s%s", "_binary_", ifn, S); \ } while (0) /* * Create symbol table. */ create_external_symtab(ecp); data_start = 0; data_end = data_start + sb.st_size; data_size = sb.st_size; _GEN_SYMNAME("_start"); add_to_symtab(ecp, name, data_start, 0, 1, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); _GEN_SYMNAME("_end"); add_to_symtab(ecp, name, data_end, 0, 1, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); _GEN_SYMNAME("_size"); add_to_symtab(ecp, name, data_size, 0, SHN_ABS, ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0, 1); finalize_external_symtab(ecp); create_symtab_data(ecp); #undef _GEN_SYMNAME /* * Write the underlying ehdr. Note that it should be called * before elf_setshstrndx() since it will overwrite e->e_shstrndx. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Generate section name string table (.shstrtab). */ ecp->flags |= SYMTAB_EXIST; set_shstrtab(ecp); /* Update sh_name pointer for each section header entry. */ update_shdr(ecp, 0); /* Properly set sh_link field of .symtab section. */ if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", elf_errmsg(-1)); sh.sh_link = elf_ndxscn(ecp->strtab->os); if (!gelf_update_shdr(ecp->symtab->os, &sh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); /* Renew oeh to get the updated e_shstrndx. */ if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Resync section offsets. */ resync_sections(ecp); /* Store SHDR offset in EHDR. */ oeh.e_shoff = shtab->off; /* Update ehdr since we modified e_shoff. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Write out the output elf object. */ if (elf_update(ecp->eout, ELF_C_WRITE) < 0) errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); /* Release allocated resource. */ free(content); free_elf(ecp); } Index: head/contrib/elftoolchain/elfcopy/elfcopy.1 =================================================================== --- head/contrib/elftoolchain/elfcopy/elfcopy.1 (revision 280931) +++ head/contrib/elftoolchain/elfcopy/elfcopy.1 (revision 280932) @@ -1,323 +1,333 @@ .\" Copyright (c) 2008-2009,2011 Joseph Koshy. All rights reserved. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" This software is provided by Joseph Koshy ``as is'' and .\" any express or implied warranties, including, but not limited to, the .\" implied warranties of merchantability and fitness for a particular purpose .\" are disclaimed. in no event shall Joseph Koshy be liable .\" for any direct, indirect, incidental, special, exemplary, or consequential .\" damages (including, but not limited to, procurement of substitute goods .\" or services; loss of use, data, or profits; or business interruption) .\" however caused and on any theory of liability, whether in contract, strict .\" liability, or tort (including negligence or otherwise) arising in any way .\" out of the use of this software, even if advised of the possibility of .\" such damage. .\" -.\" $Id: elfcopy.1 2373 2011-12-30 07:13:44Z jkoshy $ +.\" $Id: elfcopy.1 3173 2015-03-27 16:46:13Z emaste $ .\" -.Dd October 03, 2011 +.Dd March 27, 2015 .Os .Dt ELFCOPY 1 .Sh NAME .Nm elfcopy .Nd copy and translate object files .Sh SYNOPSIS .Nm .Op Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat .Op Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname .Op Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname .Op Fl N Ar symbolname | Fl -strip-symbol= Ns Ar symbolname .Op Fl O Ar objformat | Fl -output-target= Ns Ar objformat .Op Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname .Op Fl S | Fl -strip-all .Op Fl V | Fl -version .Op Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname .Op Fl X | Fl -discard-locals .Op Fl d | Fl g | Fl -strip-debug .Op Fl h | Fl -help .Op Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname .Op Fl p | Fl -preserve-dates .Op Fl w | Fl -wildcard .Op Fl x | Fl -discard-all .Op Fl -add-section Ar sectionname Ns = Ns Ar filename .Oo .Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val | .Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val .Oc .Oo .Fl -adjust-start Ns = Ns Ar increment | .Fl -change-start Ns = Ns Ar increment .Oc .Oo .Fl -adjust-vma Ns = Ns Ar increment | .Fl -change-addresses Ns = Ns Ar increment .Oc .Op Fl -adjust-warnings | Fl -change-warnings .Op Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val .Op Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val +.Op Fl -extract-dwo .Op Fl -gap-fill Ns = Ns Ar val +.Op Fl -localize-hidden .Op Fl -no-adjust-warnings | Fl -no-change-warnings .Op Fl -only-keep-debug .Op Fl -pad-to Ns = Ns Ar address .Op Fl -prefix-alloc-sections Ns = Ns Ar string .Op Fl -prefix-sections Ns = Ns Ar string .Op Fl -prefix-symbols Ns = Ns Ar string .Op Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags .Op Fl -set-section-flags Ar sectionname Ns = Ns Ar flags .Op Fl -set-start Ns = Ns Ar address .Op Fl -srec-forceS3 .Op Fl -srec-len Ns = Ns Ar val +.Op Fl -strip-dwo .Op Fl -strip-unneeded .Ar infile .Op Ar outfile .Sh DESCRIPTION The .Nm utility copies the content of the ELF object named by argument .Ar infile to that named by argument .Ar outfile , transforming it according to the command line options specified. If argument .Ar outfile is not specified, .Nm will create a temporary file and will subsequently rename it as .Ar infile . .Pp The .Nm utility supports the following options: .Bl -tag -width indent .It Fl I Ar objformat | Fl s Ar objformat | Fl -input-target= Ns Ar objformat Specify that the input file named by the argument .Ar infile is in the object format specified by the argument .Ar objformat . .It Fl K Ar symbolname | Fl -keep-symbol= Ns Ar symbolname Copy the symbol named by argument .Ar symbolname to the output. .It Fl L Ar symbolname | Fl -localize-symbol= Ns Ar symbolname Make the symbol named by argument .Ar symbolname local to the output file. .It Fl N Ar symbol | Fl -strip-symbol= Ns Ar symbolname Do not copy the symbol named by argument .Ar symbolname to the output. .It Fl O Ar objformat | Fl -output-target= Ns Ar objformat Write the output file using the object format specified in argument .Ar objformat . .It Fl R Ar sectionname | Fl -remove-section= Ns Ar sectionname Remove any section with name .Ar sectionname from the output file. .It Fl S | Fl -strip-all Do not copy symbol and relocation information to the target file. .It Fl V | Fl -version Print a version identifier and exit. .It Fl W Ar symbolname | Fl -weaken-symbol= Ns Ar symbolname Mark the symbol named by argument .Ar symbolname as weak in the output. .It Fl X | Fl -discard-locals Do not copy compiler generated local symbols to the output. .It Fl d | Fl g | Fl -strip-debug Do not copy debugging information to the target file. .It Fl h | Fl -help Display a help message and exit. .It Fl j Ar sectionname | Fl -only-section= Ns Ar sectionname Copy only the section named by argument .Ar sectionname to the output. .It Fl p | Fl -preserve-dates Set the access and modification times of the output file to the same as those of the input. .It Fl w | Fl -wildcard Use shell-style patterns to name symbols. The following meta-characters are recognized in patterns: .Bl -tag -width "...." -compact .It Li ! If this is the first character of the pattern, invert the sense of the pattern match. .It Li * Matches any string of characters in a symbol name. .It Li ? Matches zero or one character in a symbol name. .It Li [ Mark the start of a character class. .It Li \e Remove the special meaning of the next character in the pattern. .It Li ] Mark the end of a character class. .El .It Fl x | Fl -discard-all Do not copy non-global symbols to the output. .It Fl -add-section Ar sectionname Ns = Ns Ar filename Add a new section to the output file with name .Ar sectionname . The contents of the section are taken from the file named by argument .Ar filename . The size of the section will be the number of bytes in file .Ar filename . .It Xo .Fl -adjust-section-vma Ar section Ns {+|-|=} Ns Ar val | .Fl -change-section-address Ar section Ns {+|-|=} Ns Ar val .Xc Depending on the operator specified, increase, decrease or set both the virtual memory address and the load memory address of the section named by the argument .Ar section . The argument .Ar val specifies the desired increment, decrement or new value for the address. .It Xo .Fl -adjust-start Ns = Ns Ar increment | .Fl -change-start Ns = Ns Ar increment .Xc Increase the entry point address of the output ELF object by the value specified in the argument .Ar increment . .It Xo .Fl -adjust-vma Ns = Ns Ar increment | .Fl -change-addresses Ns = Ns Ar increment .Xc Increase the virtual memory address and the load memory address of all sections by the value specified by the argument .Ar increment . .It Fl -adjust-warnings | Fl -change-warnings Issue a warning if the section specified by the options .Fl -change-section-address , .Fl -change-section-lma or .Fl -change-section-vma does not exist in the input object. This is the default. .It Fl -change-section-lma Ar section Ns {+|-|=} Ns Ar val Change or set the load memory address of the section named by the argument .Ar section . Depending on the operator specified, the value in argument .Ar val will be used as an increment, a decrement or as the new value of the load memory address. .It Fl -change-section-vma Ar section Ns {+|-|=} Ns Ar val Change or set the virtual memory address of the section named by the argument .Ar section . Depending on the operator specified, the value in argument .Ar val will be used as an increment, a decrement or as the new value of the virtual memory address. +.It Fl -extract-dwo +Copy only .dwo debug sections to the output file. .It Fl -gap-fill Ns = Ns Ar val Fill the gaps between sections with the byte value specified by the argument .Ar val . +.It Fl -localize-hidden +Make all hidden symbols local to the output file. +This includes symbols with internal visiblity. .It Fl -no-adjust-warnings | Fl -no-change-warnings Do not issue a warning if the section specified by the options .Fl -change-section-address , .Fl -change-section-lma or .Fl -change-section-vma is missing in the input object. .It Fl -only-keep-debug Copy only debugging information to the output file. .It Fl -pad-to Ns = Ns Ar address Pad the load memory address of the output object to the value specified by the argument .Ar address by increasing the size of the section with the highest load memory address. .It Fl -prefix-alloc-sections Ns = Ns Ar string Prefix the section names of all the allocated sections with .Ar string . .It Fl -prefix-sections Ns = Ns Ar string Prefix the section names of all the sections with .Ar string . .It Fl -prefix-symbols Ns = Ns Ar string Prefix the symbol names of all the symbols with .Ar string . .It Fl -rename-section Ar oldname Ns = Ns Ar newname Ns Op Ar ,flags Rename the section named by argument .Ar oldname to .Ar newname , optionally changing the sections flags to that specified by argument .Ar flags . Allowed values for the argument .Ar flags are as for option .Fl -set-section-flags below. .It Fl -set-section-flags Ar sectionname Ns = Ns Ar flags Set the flags for the section named by argument .Ar sectionname to those specified by argument .Ar flags . Argument .Ar flags is a comma separated list of the following flag names: .Bl -tag -width "readonly" -compact .It alloc The section occupies space in the output file. .It code The section contains machine instructions. .It contents This flag is accepted but is ignored. .It data The section contains writeable data. .It debug The section holds debugging information. .It load The section is loadable. .It noload The section should not be loaded into memory. .It readonly The section is not writable. .It rom The section contains ROM'able contents. .It share This flag is accepted but is ignored. .El .It Fl -set-start Ns = Ns Ar address Set the start address of the output ELF object to the value specified by the argument .Ar address . .It Fl -srec-forceS3 Only generate S-records of type .Dq S3 . This option is only meaningful when the output target is set to .Dq srec . .It Fl -srec-len Ns = Ns Ar val Set the maximum length of an S-record line to .Ar val . This option is only meaningful when the output target is set to .Dq srec . +.It Fl -strip-dwo +Do not copy .dwo debug sections to the output file. .It Fl -strip-unneeded Do not copy symbols that are not needed for relocation processing. .El .Sh DIAGNOSTICS .Ex -std .Sh SEE ALSO .Xr ar 1 , .Xr ld 1 , .Xr mcs 1 , .Xr strip 1 , .Xr elf 3 , .Xr ar 5 , .Xr elf 5 .Sh HISTORY .Nm has been implemented by .An "Kai Wang" Aq kaiwang27@users.sourceforge.net . Index: head/contrib/elftoolchain/elfcopy/elfcopy.h =================================================================== --- head/contrib/elftoolchain/elfcopy/elfcopy.h (revision 280931) +++ head/contrib/elftoolchain/elfcopy/elfcopy.h (revision 280932) @@ -1,314 +1,317 @@ /*- * Copyright (c) 2007-2013 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: elfcopy.h 3134 2014-12-23 10:43:59Z kaiwang27 $ + * $Id: elfcopy.h 3173 2015-03-27 16:46:13Z emaste $ */ #include #include #include #include "_elftc.h" /* * User specified symbol operation (strip, keep, localize, globalize, * weaken, rename, etc). */ struct symop { const char *name; const char *newname; #define SYMOP_KEEP 0x0001U #define SYMOP_STRIP 0x0002U #define SYMOP_GLOBALIZE 0x0004U #define SYMOP_LOCALIZE 0x0008U #define SYMOP_KEEPG 0x0010U #define SYMOP_WEAKEN 0x0020U #define SYMOP_REDEF 0x0040U unsigned int op; STAILQ_ENTRY(symop) symop_list; }; /* File containing symbol list. */ struct symfile { dev_t dev; ino_t ino; size_t size; char *data; unsigned int op; STAILQ_ENTRY(symfile) symfile_list; }; /* Sections to copy/remove/rename/... */ struct sec_action { const char *name; const char *addopt; const char *newname; const char *string; uint64_t lma; uint64_t vma; int64_t lma_adjust; int64_t vma_adjust; #define SF_ALLOC 0x0001U #define SF_LOAD 0x0002U #define SF_NOLOAD 0x0004U #define SF_READONLY 0x0008U #define SF_DEBUG 0x0010U #define SF_CODE 0x0020U #define SF_DATA 0x0040U #define SF_ROM 0x0080U #define SF_SHARED 0X0100U #define SF_CONTENTS 0x0200U int flags; int add; int append; int compress; int copy; int print; int remove; int rename; int setflags; int setlma; int setvma; STAILQ_ENTRY(sec_action) sac_list; }; /* Sections to add from file. */ struct sec_add { char *name; char *content; size_t size; STAILQ_ENTRY(sec_add) sadd_list; }; struct segment; /* Internal data structure for sections. */ struct section { struct segment *seg; /* containing segment */ struct segment *seg_tls; /* tls segment */ const char *name; /* section name */ char *newname; /* new section name */ Elf_Scn *is; /* input scn */ Elf_Scn *os; /* output scn */ void *buf; /* section content */ uint8_t *pad; /* section padding */ uint64_t off; /* section offset */ uint64_t sz; /* section size */ uint64_t cap; /* section capacity */ uint64_t align; /* section alignment */ uint64_t type; /* section type */ uint64_t vma; /* section virtual addr */ uint64_t lma; /* section load addr */ uint64_t pad_sz;/* section padding size */ int loadable; /* whether loadable */ int pseudo; int nocopy; TAILQ_ENTRY(section) sec_list; /* next section */ }; /* Internal data structure for segments. */ struct segment { uint64_t addr; /* load addr */ uint64_t off; /* file offset */ uint64_t fsz; /* file size */ uint64_t msz; /* memory size */ uint64_t type; /* segment type */ int remove; /* whether remove */ int nsec; /* number of sections contained */ struct section **v_sec; /* list of sections contained */ STAILQ_ENTRY(segment) seg_list; /* next segment */ }; /* * In-memory representation of ar(1) archive member(object). */ struct ar_obj { char *name; /* member name */ char *buf; /* member content */ void *maddr; /* mmap start address */ uid_t uid; /* user id */ gid_t gid; /* group id */ mode_t md; /* octal file permissions */ size_t size; /* member size */ time_t mtime; /* modification time */ STAILQ_ENTRY(ar_obj) objs; }; /* * Structure encapsulates the "global" data for "elfcopy" program. */ struct elfcopy { const char *progname; /* program name */ int iec; /* elfclass of input object */ Elftc_Bfd_Target_Flavor itf; /* flavour of input object */ Elftc_Bfd_Target_Flavor otf; /* flavour of output object */ const char *otgt; /* output target name */ int oec; /* elfclass of output object */ unsigned char oed; /* endianess of output object */ int oem; /* EM_XXX of output object */ int abi; /* OSABI of output object */ Elf *ein; /* ELF descriptor of input object */ Elf *eout; /* ELF descriptor of output object */ int iphnum; /* num. of input object phdr entries */ int ophnum; /* num. of output object phdr entries */ int nos; /* num. of output object sections */ enum { STRIP_NONE = 0, STRIP_ALL, STRIP_DEBUG, + STRIP_DWO, STRIP_NONDEBUG, + STRIP_NONDWO, STRIP_UNNEEDED } strip; #define EXECUTABLE 0x00000001U #define DYNAMIC 0x00000002U #define RELOCATABLE 0x00000004U #define SYMTAB_EXIST 0x00000010U #define SYMTAB_INTACT 0x00000020U #define KEEP_GLOBAL 0x00000040U #define DISCARD_LOCAL 0x00000080U #define WEAKEN_ALL 0x00000100U #define PRESERVE_DATE 0x00001000U #define SREC_FORCE_S3 0x00002000U #define SREC_FORCE_LEN 0x00004000U #define SET_START 0x00008000U #define GAP_FILL 0x00010000U #define WILDCARD 0x00020000U #define NO_CHANGE_WARN 0x00040000U #define SEC_ADD 0x00080000U #define SEC_APPEND 0x00100000U #define SEC_COMPRESS 0x00200000U #define SEC_PRINT 0x00400000U #define SEC_REMOVE 0x00800000U #define SEC_COPY 0x01000000U #define DISCARD_LLABEL 0x02000000U +#define LOCALIZE_HIDDEN 0x04000000U int flags; /* elfcopy run control flags. */ int64_t change_addr; /* Section address adjustment. */ int64_t change_start; /* Entry point adjustment. */ uint64_t set_start; /* Entry point value. */ unsigned long srec_len; /* S-Record length. */ uint64_t pad_to; /* load address padding. */ uint8_t fill; /* gap fill value. */ char *prefix_sec; /* section prefix. */ char *prefix_alloc; /* alloc section prefix. */ char *prefix_sym; /* symbol prefix. */ char *debuglink; /* GNU debuglink file. */ struct section *symtab; /* .symtab section. */ struct section *strtab; /* .strtab section. */ struct section *shstrtab; /* .shstrtab section. */ uint64_t *secndx; /* section index map. */ uint64_t *symndx; /* symbol index map. */ unsigned char *v_rel; /* symbols needed by relocation. */ unsigned char *v_secsym; /* sections with section symbol. */ STAILQ_HEAD(, segment) v_seg; /* list of segments. */ STAILQ_HEAD(, sec_action) v_sac;/* list of section operations. */ STAILQ_HEAD(, sec_add) v_sadd; /* list of sections to add. */ STAILQ_HEAD(, symop) v_symop; /* list of symbols operations. */ STAILQ_HEAD(, symfile) v_symfile; /* list of symlist files. */ TAILQ_HEAD(, section) v_sec; /* list of sections. */ /* * Fields for the ar(1) archive. */ char *as; /* buffer for archive string table. */ size_t as_sz; /* current size of as table. */ size_t as_cap; /* capacity of as table buffer. */ uint32_t s_cnt; /* current number of symbols. */ uint32_t *s_so; /* symbol offset table. */ size_t s_so_cap; /* capacity of so table buffer. */ char *s_sn; /* symbol name table */ size_t s_sn_cap; /* capacity of sn table buffer. */ size_t s_sn_sz; /* current size of sn table. */ off_t rela_off; /* offset relative to pseudo members. */ STAILQ_HEAD(, ar_obj) v_arobj; /* archive object(member) list. */ }; void add_section(struct elfcopy *_ecp, const char *_optarg); void add_to_shstrtab(struct elfcopy *_ecp, const char *_name); void add_to_symop_list(struct elfcopy *_ecp, const char *_name, const char *_newname, unsigned int _op); void add_to_symtab(struct elfcopy *_ecp, const char *_name, uint64_t _st_value, uint64_t _st_size, uint16_t _st_shndx, unsigned char _st_info, unsigned char _st_other, int _ndx_known); int add_to_inseg_list(struct elfcopy *_ecp, struct section *_sec); void adjust_addr(struct elfcopy *_ecp); void copy_content(struct elfcopy *_ecp); void copy_data(struct section *_s); void copy_phdr(struct elfcopy *_ecp); void copy_shdr(struct elfcopy *_ecp, struct section *_s, const char *_name, int _copy, int _sec_flags); void create_binary(int _ifd, int _ofd); void create_elf(struct elfcopy *_ecp); void create_elf_from_binary(struct elfcopy *_ecp, int _ifd, const char *ifn); void create_elf_from_ihex(struct elfcopy *_ecp, int _ifd); void create_elf_from_srec(struct elfcopy *_ecp, int _ifd); struct section *create_external_section(struct elfcopy *_ecp, const char *_name, char *_newname, void *_buf, uint64_t _size, uint64_t _off, uint64_t _stype, Elf_Type _dtype, uint64_t flags, uint64_t _align, uint64_t _vma, int _loadable); void create_external_symtab(struct elfcopy *_ecp); void create_ihex(int _ifd, int _ofd); void create_scn(struct elfcopy *_ecp); void create_srec(struct elfcopy *_ecp, int _ifd, int _ofd, const char *_ofn); void create_symtab(struct elfcopy *_ecp); void create_symtab_data(struct elfcopy *_ecp); void create_tempfile(char **_fn, int *_fd); void finalize_external_symtab(struct elfcopy *_ecp); void free_elf(struct elfcopy *_ecp); void free_sec_act(struct elfcopy *_ecp); void free_sec_add(struct elfcopy *_ecp); void free_symtab(struct elfcopy *_ecp); void init_shstrtab(struct elfcopy *_ecp); void insert_to_sec_list(struct elfcopy *_ecp, struct section *_sec, int _tail); struct section *insert_shtab(struct elfcopy *_ecp, int tail); int is_remove_reloc_sec(struct elfcopy *_ecp, uint32_t _sh_info); int is_remove_section(struct elfcopy *_ecp, const char *_name); struct sec_action *lookup_sec_act(struct elfcopy *_ecp, const char *_name, int _add); struct symop *lookup_symop_list(struct elfcopy *_ecp, const char *_name, unsigned int _op); void resync_sections(struct elfcopy *_ecp); void set_shstrtab(struct elfcopy *_ecp); void setup_phdr(struct elfcopy *_ecp); void update_shdr(struct elfcopy *_ecp, int _update_link); #ifndef LIBELF_AR int ac_detect_ar(int _ifd); void ac_create_ar(struct elfcopy *_ecp, int _ifd, int _ofd); #endif /* ! LIBELF_AR */ Index: head/contrib/elftoolchain/elfcopy/main.c =================================================================== --- head/contrib/elftoolchain/elfcopy/main.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/main.c (revision 280932) @@ -1,1513 +1,1530 @@ /*- * Copyright (c) 2007-2013 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: main.c 3156 2015-02-15 21:40:01Z emaste $"); +ELFTC_VCSID("$Id: main.c 3174 2015-03-27 17:13:41Z emaste $"); enum options { ECP_ADD_GNU_DEBUGLINK, ECP_ADD_SECTION, ECP_CHANGE_ADDR, ECP_CHANGE_SEC_ADDR, ECP_CHANGE_SEC_LMA, ECP_CHANGE_SEC_VMA, ECP_CHANGE_START, ECP_CHANGE_WARN, ECP_GAP_FILL, ECP_GLOBALIZE_SYMBOL, ECP_GLOBALIZE_SYMBOLS, ECP_KEEP_SYMBOLS, ECP_KEEP_GLOBAL_SYMBOLS, + ECP_LOCALIZE_HIDDEN, ECP_LOCALIZE_SYMBOLS, ECP_NO_CHANGE_WARN, ECP_ONLY_DEBUG, + ECP_ONLY_DWO, ECP_PAD_TO, ECP_PREFIX_ALLOC, ECP_PREFIX_SEC, ECP_PREFIX_SYM, ECP_REDEF_SYMBOL, ECP_REDEF_SYMBOLS, ECP_RENAME_SECTION, ECP_SET_OSABI, ECP_SET_SEC_FLAGS, ECP_SET_START, ECP_SREC_FORCE_S3, ECP_SREC_LEN, + ECP_STRIP_DWO, ECP_STRIP_SYMBOLS, ECP_STRIP_UNNEEDED, ECP_WEAKEN_ALL, ECP_WEAKEN_SYMBOLS }; static struct option mcs_longopts[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; static struct option strip_longopts[] = { {"discard-all", no_argument, NULL, 'x'}, {"discard-locals", no_argument, NULL, 'X'}, {"help", no_argument, NULL, 'h'}, {"input-target", required_argument, NULL, 'I'}, {"keep-symbol", required_argument, NULL, 'K'}, {"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG}, {"output-file", required_argument, NULL, 'o'}, {"output-target", required_argument, NULL, 'O'}, {"preserve-dates", no_argument, NULL, 'p'}, {"remove-section", required_argument, NULL, 'R'}, {"strip-all", no_argument, NULL, 's'}, {"strip-debug", no_argument, NULL, 'S'}, {"strip-symbol", required_argument, NULL, 'N'}, {"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED}, {"version", no_argument, NULL, 'V'}, {"wildcard", no_argument, NULL, 'w'}, {NULL, 0, NULL, 0} }; static struct option elfcopy_longopts[] = { {"add-gnu-debuglink", required_argument, NULL, ECP_ADD_GNU_DEBUGLINK}, {"add-section", required_argument, NULL, ECP_ADD_SECTION}, {"adjust-section-vma", required_argument, NULL, ECP_CHANGE_SEC_ADDR}, {"adjust-vma", required_argument, NULL, ECP_CHANGE_ADDR}, {"adjust-start", required_argument, NULL, ECP_CHANGE_START}, {"adjust-warnings", no_argument, NULL, ECP_CHANGE_WARN}, {"binary-architecture", required_argument, NULL, 'B'}, {"change-addresses", required_argument, NULL, ECP_CHANGE_ADDR}, {"change-section-address", required_argument, NULL, ECP_CHANGE_SEC_ADDR}, {"change-section-lma", required_argument, NULL, ECP_CHANGE_SEC_LMA}, {"change-section-vma", required_argument, NULL, ECP_CHANGE_SEC_VMA}, {"change-start", required_argument, NULL, ECP_CHANGE_START}, {"change-warnings", no_argument, NULL, ECP_CHANGE_WARN}, {"discard-all", no_argument, NULL, 'x'}, {"discard-locals", no_argument, NULL, 'X'}, + {"extract-dwo", no_argument, NULL, ECP_ONLY_DWO}, {"gap-fill", required_argument, NULL, ECP_GAP_FILL}, {"globalize-symbol", required_argument, NULL, ECP_GLOBALIZE_SYMBOL}, {"globalize-symbols", required_argument, NULL, ECP_GLOBALIZE_SYMBOLS}, {"help", no_argument, NULL, 'h'}, {"input-target", required_argument, NULL, 'I'}, {"keep-symbol", required_argument, NULL, 'K'}, {"keep-symbols", required_argument, NULL, ECP_KEEP_SYMBOLS}, {"keep-global-symbol", required_argument, NULL, 'G'}, {"keep-global-symbols", required_argument, NULL, ECP_KEEP_GLOBAL_SYMBOLS}, + {"localize-hidden", no_argument, NULL, ECP_LOCALIZE_HIDDEN}, {"localize-symbol", required_argument, NULL, 'L'}, {"localize-symbols", required_argument, NULL, ECP_LOCALIZE_SYMBOLS}, {"no-adjust-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN}, {"no-change-warnings", no_argument, NULL, ECP_NO_CHANGE_WARN}, {"only-keep-debug", no_argument, NULL, ECP_ONLY_DEBUG}, {"only-section", required_argument, NULL, 'j'}, {"osabi", required_argument, NULL, ECP_SET_OSABI}, {"output-target", required_argument, NULL, 'O'}, {"pad-to", required_argument, NULL, ECP_PAD_TO}, {"preserve-dates", no_argument, NULL, 'p'}, {"prefix-alloc-sections", required_argument, NULL, ECP_PREFIX_ALLOC}, {"prefix-sections", required_argument, NULL, ECP_PREFIX_SEC}, {"prefix-symbols", required_argument, NULL, ECP_PREFIX_SYM}, {"redefine-sym", required_argument, NULL, ECP_REDEF_SYMBOL}, {"redefine-syms", required_argument, NULL, ECP_REDEF_SYMBOLS}, {"remove-section", required_argument, NULL, 'R'}, {"rename-section", required_argument, NULL, ECP_RENAME_SECTION}, {"set-section-flags", required_argument, NULL, ECP_SET_SEC_FLAGS}, {"set-start", required_argument, NULL, ECP_SET_START}, {"srec-forceS3", no_argument, NULL, ECP_SREC_FORCE_S3}, {"srec-len", required_argument, NULL, ECP_SREC_LEN}, {"strip-all", no_argument, NULL, 'S'}, {"strip-debug", no_argument, 0, 'g'}, + {"strip-dwo", no_argument, NULL, ECP_STRIP_DWO}, {"strip-symbol", required_argument, NULL, 'N'}, {"strip-symbols", required_argument, NULL, ECP_STRIP_SYMBOLS}, {"strip-unneeded", no_argument, NULL, ECP_STRIP_UNNEEDED}, {"version", no_argument, NULL, 'V'}, {"weaken", no_argument, NULL, ECP_WEAKEN_ALL}, {"weaken-symbol", required_argument, NULL, 'W'}, {"weaken-symbols", required_argument, NULL, ECP_WEAKEN_SYMBOLS}, {"wildcard", no_argument, NULL, 'w'}, {NULL, 0, NULL, 0} }; static struct { const char *name; int value; } sec_flags[] = { {"alloc", SF_ALLOC}, {"load", SF_LOAD}, {"noload", SF_NOLOAD}, {"readonly", SF_READONLY}, {"debug", SF_DEBUG}, {"code", SF_CODE}, {"data", SF_DATA}, {"rom", SF_ROM}, {"share", SF_SHARED}, {"contents", SF_CONTENTS}, {NULL, 0} }; static struct { const char *name; int abi; } osabis[] = { {"sysv", ELFOSABI_SYSV}, {"hpus", ELFOSABI_HPUX}, {"netbsd", ELFOSABI_NETBSD}, {"linux", ELFOSABI_LINUX}, {"hurd", ELFOSABI_HURD}, {"86open", ELFOSABI_86OPEN}, {"solaris", ELFOSABI_SOLARIS}, {"aix", ELFOSABI_AIX}, {"irix", ELFOSABI_IRIX}, {"freebsd", ELFOSABI_FREEBSD}, {"tru64", ELFOSABI_TRU64}, {"modesto", ELFOSABI_MODESTO}, {"openbsd", ELFOSABI_OPENBSD}, {"openvms", ELFOSABI_OPENVMS}, {"nsk", ELFOSABI_NSK}, {"arm", ELFOSABI_ARM}, {"standalone", ELFOSABI_STANDALONE}, {NULL, 0} }; static int copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd, int in_place); static void create_file(struct elfcopy *ecp, const char *src, const char *dst); static void elfcopy_main(struct elfcopy *ecp, int argc, char **argv); static void elfcopy_usage(void); static void mcs_main(struct elfcopy *ecp, int argc, char **argv); static void mcs_usage(void); static void parse_sec_address_op(struct elfcopy *ecp, int optnum, const char *optname, char *s); static void parse_sec_flags(struct sec_action *sac, char *s); static void parse_symlist_file(struct elfcopy *ecp, const char *fn, unsigned int op); static void print_version(void); static void set_input_target(struct elfcopy *ecp, const char *target_name); static void set_osabi(struct elfcopy *ecp, const char *abi); static void set_output_target(struct elfcopy *ecp, const char *target_name); static void strip_main(struct elfcopy *ecp, int argc, char **argv); static void strip_usage(void); /* * An ELF object usually has a sturcture described by the * diagram below. * _____________ * | | * | NULL | <- always a SHT_NULL section * |_____________| * | | * | .interp | * |_____________| * | | * | ... | * |_____________| * | | * | .text | * |_____________| * | | * | ... | * |_____________| * | | * | .comment | <- above(include) this: normal sections * |_____________| * | | * | add sections| <- unloadable sections added by --add-section * |_____________| * | | * | .shstrtab | <- section name string table * |_____________| * | | * | shdrs | <- section header table * |_____________| * | | * | .symtab | <- symbol table, if any * |_____________| * | | * | .strtab | <- symbol name string table, if any * |_____________| * | | * | .rel.text | <- relocation info for .o files. * |_____________| */ void create_elf(struct elfcopy *ecp) { struct section *shtab; GElf_Ehdr ieh; GElf_Ehdr oeh; size_t ishnum; ecp->flags |= SYMTAB_INTACT; /* Create EHDR. */ if (gelf_getehdr(ecp->ein, &ieh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); if ((ecp->iec = gelf_getclass(ecp->ein)) == ELFCLASSNONE) errx(EXIT_FAILURE, "getclass() failed: %s", elf_errmsg(-1)); if (ecp->oec == ELFCLASSNONE) ecp->oec = ecp->iec; if (ecp->oed == ELFDATANONE) ecp->oed = ieh.e_ident[EI_DATA]; if (gelf_newehdr(ecp->eout, ecp->oec) == NULL) errx(EXIT_FAILURE, "gelf_newehdr failed: %s", elf_errmsg(-1)); if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); memcpy(oeh.e_ident, ieh.e_ident, sizeof(ieh.e_ident)); oeh.e_ident[EI_CLASS] = ecp->oec; oeh.e_ident[EI_DATA] = ecp->oed; if (ecp->abi != -1) oeh.e_ident[EI_OSABI] = ecp->abi; oeh.e_flags = ieh.e_flags; oeh.e_machine = ieh.e_machine; oeh.e_type = ieh.e_type; oeh.e_entry = ieh.e_entry; oeh.e_version = ieh.e_version; if (ieh.e_type == ET_EXEC) ecp->flags |= EXECUTABLE; else if (ieh.e_type == ET_DYN) ecp->flags |= DYNAMIC; else if (ieh.e_type == ET_REL) ecp->flags |= RELOCATABLE; else errx(EXIT_FAILURE, "unsupported e_type"); if (!elf_getshnum(ecp->ein, &ishnum)) errx(EXIT_FAILURE, "elf_getshnum failed: %s", elf_errmsg(-1)); if (ishnum > 0 && (ecp->secndx = calloc(ishnum, sizeof(*ecp->secndx))) == NULL) err(EXIT_FAILURE, "calloc failed"); /* Read input object program header. */ setup_phdr(ecp); /* * Scan of input sections: we iterate through sections from input * object, skip sections need to be stripped, allot Elf_Scn and * create internal section structure for sections we want. * (i.e., determine output sections) */ create_scn(ecp); /* Apply section address changes, if any. */ adjust_addr(ecp); /* * Determine if the symbol table needs to be changed based on * command line options. */ if (ecp->strip == STRIP_DEBUG || ecp->strip == STRIP_UNNEEDED || ecp->flags & WEAKEN_ALL || + ecp->flags & LOCALIZE_HIDDEN || ecp->flags & DISCARD_LOCAL || ecp->flags & DISCARD_LLABEL || ecp->prefix_sym != NULL || !STAILQ_EMPTY(&ecp->v_symop)) ecp->flags &= ~SYMTAB_INTACT; /* * Create symbol table. Symbols are filtered or stripped according to * command line args specified by user, and later updated for the new * layout of sections in the output object. */ if ((ecp->flags & SYMTAB_EXIST) != 0) create_symtab(ecp); /* * First processing of output sections: at this stage we copy the * content of each section from input to output object. Section * content will be modified and printed (mcs) if need. Also content of * relocation section probably will be filtered and updated according * to symbol table changes. */ copy_content(ecp); /* * Write the underlying ehdr. Note that it should be called * before elf_setshstrndx() since it will overwrite e->e_shstrndx. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); /* Generate section name string table (.shstrtab). */ set_shstrtab(ecp); /* * Second processing of output sections: Update section headers. * At this stage we set name string index, update st_link and st_info * for output sections. */ update_shdr(ecp, 1); /* Renew oeh to get the updated e_shstrndx. */ if (gelf_getehdr(ecp->eout, &oeh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* * Insert SHDR table into the internal section list as a "pseudo" * section, so later it will get sorted and resynced just as "normal" * sections. */ shtab = insert_shtab(ecp, 0); /* * Resync section offsets in the output object. This is needed * because probably sections are modified or new sections are added, * as a result overlap/gap might appears. */ resync_sections(ecp); /* Store SHDR offset in EHDR. */ oeh.e_shoff = shtab->off; /* Put program header table immediately after the Elf header. */ if (ecp->ophnum > 0) { oeh.e_phoff = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); if (oeh.e_phoff == 0) errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); } /* * Update ELF object entry point if requested. */ if (ecp->change_addr != 0) oeh.e_entry += ecp->change_addr; if (ecp->flags & SET_START) oeh.e_entry = ecp->set_start; if (ecp->change_start != 0) oeh.e_entry += ecp->change_start; /* * Update ehdr again before we call elf_update(), since we * modified e_shoff and e_phoff. */ if (gelf_update_ehdr(ecp->eout, &oeh) == 0) errx(EXIT_FAILURE, "gelf_update_ehdr() failed: %s", elf_errmsg(-1)); if (ecp->ophnum > 0) copy_phdr(ecp); /* Write out the output elf object. */ if (elf_update(ecp->eout, ELF_C_WRITE) < 0) errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); /* Release allocated resource. */ free_elf(ecp); } void free_elf(struct elfcopy *ecp) { struct segment *seg, *seg_temp; struct section *sec, *sec_temp; /* Free internal segment list. */ if (!STAILQ_EMPTY(&ecp->v_seg)) { STAILQ_FOREACH_SAFE(seg, &ecp->v_seg, seg_list, seg_temp) { STAILQ_REMOVE(&ecp->v_seg, seg, segment, seg_list); free(seg); } } /* Free symbol table buffers. */ free_symtab(ecp); /* Free internal section list. */ if (!TAILQ_EMPTY(&ecp->v_sec)) { TAILQ_FOREACH_SAFE(sec, &ecp->v_sec, sec_list, sec_temp) { TAILQ_REMOVE(&ecp->v_sec, sec, sec_list); if (sec->buf != NULL) free(sec->buf); if (sec->newname != NULL) free(sec->newname); if (sec->pad != NULL) free(sec->pad); free(sec); } } } /* Create a temporary file. */ void create_tempfile(char **fn, int *fd) { const char *tmpdir; char *cp, *tmpf; size_t tlen, plen; #define _TEMPFILE "ecp.XXXXXXXX" #define _TEMPFILEPATH "/tmp/ecp.XXXXXXXX" if (fn == NULL || fd == NULL) return; /* Repect TMPDIR environment variable. */ tmpdir = getenv("TMPDIR"); if (tmpdir != NULL && *tmpdir != '\0') { tlen = strlen(tmpdir); plen = strlen(_TEMPFILE); tmpf = malloc(tlen + plen + 2); if (tmpf == NULL) err(EXIT_FAILURE, "malloc failed"); strncpy(tmpf, tmpdir, tlen); cp = &tmpf[tlen - 1]; if (*cp++ != '/') *cp++ = '/'; strncpy(cp, _TEMPFILE, plen); cp[plen] = '\0'; } else { tmpf = strdup(_TEMPFILEPATH); if (tmpf == NULL) err(EXIT_FAILURE, "strdup failed"); } if ((*fd = mkstemp(tmpf)) == -1) err(EXIT_FAILURE, "mkstemp %s failed", tmpf); if (fchmod(*fd, 0644) == -1) err(EXIT_FAILURE, "fchmod %s failed", tmpf); *fn = tmpf; #undef _TEMPFILE #undef _TEMPFILEPATH } /* * Copy temporary file with path src and file descriptor infd to path dst. * If in_place is set act as if editing the file in place, avoiding rename() * to preserve hard and symbolic links. Output file remains open, with file * descriptor returned in outfd. */ static int copy_from_tempfile(const char *src, const char *dst, int infd, int *outfd, int in_place) { int tmpfd; /* * First, check if we can use rename(). */ if (in_place == 0) { if (rename(src, dst) >= 0) { *outfd = infd; return (0); } else if (errno != EXDEV) return (-1); /* * If the rename() failed due to 'src' and 'dst' residing in * two different file systems, invoke a helper function in * libelftc to do the copy. */ if (unlink(dst) < 0) return (-1); } if ((tmpfd = open(dst, O_CREAT | O_TRUNC | O_WRONLY, 0755)) < 0) return (-1); if (elftc_copyfile(infd, tmpfd) < 0) return (-1); /* * Remove the temporary file from the file system * namespace, and close its file descriptor. */ if (unlink(src) < 0) return (-1); (void) close(infd); /* * Return the file descriptor for the destination. */ *outfd = tmpfd; return (0); } static void create_file(struct elfcopy *ecp, const char *src, const char *dst) { struct stat sb; char *tempfile, *elftemp; int efd, ifd, ofd, ofd0, tfd; int in_place; tempfile = NULL; if (src == NULL) errx(EXIT_FAILURE, "internal: src == NULL"); if ((ifd = open(src, O_RDONLY)) == -1) err(EXIT_FAILURE, "open %s failed", src); if (fstat(ifd, &sb) == -1) err(EXIT_FAILURE, "fstat %s failed", src); if (dst == NULL) create_tempfile(&tempfile, &ofd); else if ((ofd = open(dst, O_RDWR|O_CREAT, 0755)) == -1) err(EXIT_FAILURE, "open %s failed", dst); #ifndef LIBELF_AR /* Detect and process ar(1) archive using libarchive. */ if (ac_detect_ar(ifd)) { ac_create_ar(ecp, ifd, ofd); goto copy_done; } #endif if (lseek(ifd, 0, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek failed"); /* * If input object is not ELF file, convert it to an intermediate * ELF object before processing. */ if (ecp->itf != ETF_ELF) { create_tempfile(&elftemp, &efd); if ((ecp->eout = elf_begin(efd, ELF_C_WRITE, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); if (ecp->itf == ETF_BINARY) create_elf_from_binary(ecp, ifd, src); else if (ecp->itf == ETF_IHEX) create_elf_from_ihex(ecp, ifd); else if (ecp->itf == ETF_SREC) create_elf_from_srec(ecp, ifd); else errx(EXIT_FAILURE, "Internal: invalid target flavour"); elf_end(ecp->eout); /* Open intermediate ELF object as new input object. */ close(ifd); if ((ifd = open(elftemp, O_RDONLY)) == -1) err(EXIT_FAILURE, "open %s failed", src); close(efd); free(elftemp); } if ((ecp->ein = elf_begin(ifd, ELF_C_READ, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); switch (elf_kind(ecp->ein)) { case ELF_K_NONE: errx(EXIT_FAILURE, "file format not recognized"); case ELF_K_ELF: if ((ecp->eout = elf_begin(ofd, ELF_C_WRITE, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1)); /* elfcopy(1) manage ELF layout by itself. */ elf_flagelf(ecp->eout, ELF_C_SET, ELF_F_LAYOUT); /* * Create output ELF object. */ create_elf(ecp); elf_end(ecp->eout); /* * Convert the output ELF object to binary/srec/ihex if need. */ if (ecp->otf != ETF_ELF) { /* * Create (another) tempfile for binary/srec/ihex * output object. */ if (tempfile != NULL) { if (unlink(tempfile) < 0) err(EXIT_FAILURE, "unlink %s failed", tempfile); free(tempfile); } create_tempfile(&tempfile, &ofd0); /* * Rewind the file descriptor being processed. */ if (lseek(ofd, 0, SEEK_SET) < 0) err(EXIT_FAILURE, "lseek failed for the output object"); /* * Call flavour-specific conversion routine. */ switch (ecp->otf) { case ETF_BINARY: create_binary(ofd, ofd0); break; case ETF_IHEX: create_ihex(ofd, ofd0); break; case ETF_SREC: create_srec(ecp, ofd, ofd0, dst != NULL ? dst : src); break; default: errx(EXIT_FAILURE, "Internal: unsupported" " output flavour %d", ecp->oec); } close(ofd); ofd = ofd0; } break; case ELF_K_AR: /* XXX: Not yet supported. */ break; default: errx(EXIT_FAILURE, "file format not supported"); } elf_end(ecp->ein); #ifndef LIBELF_AR copy_done: #endif if (tempfile != NULL) { in_place = 0; if (dst == NULL) { dst = src; if (lstat(dst, &sb) != -1 && (sb.st_nlink > 1 || S_ISLNK(sb.st_mode))) in_place = 1; } if (copy_from_tempfile(tempfile, dst, ofd, &tfd, in_place) < 0) err(EXIT_FAILURE, "creation of %s failed", dst); free(tempfile); tempfile = NULL; ofd = tfd; } if (strcmp(dst, "/dev/null") && fchmod(ofd, sb.st_mode) == -1) err(EXIT_FAILURE, "fchmod %s failed", dst); if ((ecp->flags & PRESERVE_DATE) && elftc_set_timestamps(dst, &sb) < 0) err(EXIT_FAILURE, "setting timestamps failed"); close(ifd); close(ofd); } static void elfcopy_main(struct elfcopy *ecp, int argc, char **argv) { struct sec_action *sac; const char *infile, *outfile; char *fn, *s; int opt; while ((opt = getopt_long(argc, argv, "dB:gG:I:j:K:L:N:O:pR:s:SwW:xXV", elfcopy_longopts, NULL)) != -1) { switch(opt) { case 'B': /* ignored */ break; case 'R': sac = lookup_sec_act(ecp, optarg, 1); if (sac->copy != 0) errx(EXIT_FAILURE, "both copy and remove specified"); sac->remove = 1; ecp->flags |= SEC_REMOVE; break; case 'S': ecp->strip = STRIP_ALL; break; case 'g': ecp->strip = STRIP_DEBUG; break; case 'G': ecp->flags |= KEEP_GLOBAL; add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEPG); break; case 'I': case 's': set_input_target(ecp, optarg); break; case 'j': sac = lookup_sec_act(ecp, optarg, 1); if (sac->remove != 0) errx(EXIT_FAILURE, "both copy and remove specified"); sac->copy = 1; ecp->flags |= SEC_COPY; break; case 'K': add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP); break; case 'L': add_to_symop_list(ecp, optarg, NULL, SYMOP_LOCALIZE); break; case 'N': add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP); break; case 'O': set_output_target(ecp, optarg); break; case 'p': ecp->flags |= PRESERVE_DATE; break; case 'V': print_version(); break; case 'w': ecp->flags |= WILDCARD; break; case 'W': add_to_symop_list(ecp, optarg, NULL, SYMOP_WEAKEN); break; case 'x': ecp->flags |= DISCARD_LOCAL; break; case 'X': ecp->flags |= DISCARD_LLABEL; break; case ECP_ADD_GNU_DEBUGLINK: ecp->debuglink = optarg; break; case ECP_ADD_SECTION: add_section(ecp, optarg); break; case ECP_CHANGE_ADDR: ecp->change_addr = (int64_t) strtoll(optarg, NULL, 0); break; case ECP_CHANGE_SEC_ADDR: parse_sec_address_op(ecp, opt, "--change-section-addr", optarg); break; case ECP_CHANGE_SEC_LMA: parse_sec_address_op(ecp, opt, "--change-section-lma", optarg); break; case ECP_CHANGE_SEC_VMA: parse_sec_address_op(ecp, opt, "--change-section-vma", optarg); break; case ECP_CHANGE_START: ecp->change_start = (int64_t) strtoll(optarg, NULL, 0); break; case ECP_CHANGE_WARN: /* default */ break; case ECP_GAP_FILL: ecp->fill = (uint8_t) strtoul(optarg, NULL, 0); ecp->flags |= GAP_FILL; break; case ECP_GLOBALIZE_SYMBOL: add_to_symop_list(ecp, optarg, NULL, SYMOP_GLOBALIZE); break; case ECP_GLOBALIZE_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_GLOBALIZE); break; case ECP_KEEP_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_KEEP); break; case ECP_KEEP_GLOBAL_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_KEEPG); break; + case ECP_LOCALIZE_HIDDEN: + ecp->flags |= LOCALIZE_HIDDEN; + break; case ECP_LOCALIZE_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_LOCALIZE); break; case ECP_NO_CHANGE_WARN: ecp->flags |= NO_CHANGE_WARN; break; case ECP_ONLY_DEBUG: ecp->strip = STRIP_NONDEBUG; break; + case ECP_ONLY_DWO: + ecp->strip = STRIP_NONDWO; + break; case ECP_PAD_TO: ecp->pad_to = (uint64_t) strtoull(optarg, NULL, 0); break; case ECP_PREFIX_ALLOC: ecp->prefix_alloc = optarg; break; case ECP_PREFIX_SEC: ecp->prefix_sec = optarg; break; case ECP_PREFIX_SYM: ecp->prefix_sym = optarg; break; case ECP_REDEF_SYMBOL: if ((s = strchr(optarg, '=')) == NULL) errx(EXIT_FAILURE, "illegal format for --redefine-sym"); *s++ = '\0'; add_to_symop_list(ecp, optarg, s, SYMOP_REDEF); break; case ECP_REDEF_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_REDEF); break; case ECP_RENAME_SECTION: if ((fn = strchr(optarg, '=')) == NULL) errx(EXIT_FAILURE, "illegal format for --rename-section"); *fn++ = '\0'; /* Check for optional flags. */ if ((s = strchr(fn, ',')) != NULL) *s++ = '\0'; sac = lookup_sec_act(ecp, optarg, 1); sac->rename = 1; sac->newname = fn; if (s != NULL) parse_sec_flags(sac, s); break; case ECP_SET_OSABI: set_osabi(ecp, optarg); break; case ECP_SET_SEC_FLAGS: if ((s = strchr(optarg, '=')) == NULL) errx(EXIT_FAILURE, "illegal format for --set-section-flags"); *s++ = '\0'; sac = lookup_sec_act(ecp, optarg, 1); parse_sec_flags(sac, s); break; case ECP_SET_START: ecp->flags |= SET_START; ecp->set_start = (uint64_t) strtoull(optarg, NULL, 0); break; case ECP_SREC_FORCE_S3: ecp->flags |= SREC_FORCE_S3; break; case ECP_SREC_LEN: ecp->flags |= SREC_FORCE_LEN; ecp->srec_len = strtoul(optarg, NULL, 0); break; + case ECP_STRIP_DWO: + ecp->strip = STRIP_DWO; + break; case ECP_STRIP_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_STRIP); break; case ECP_STRIP_UNNEEDED: ecp->strip = STRIP_UNNEEDED; break; case ECP_WEAKEN_ALL: ecp->flags |= WEAKEN_ALL; break; case ECP_WEAKEN_SYMBOLS: parse_symlist_file(ecp, optarg, SYMOP_WEAKEN); break; default: elfcopy_usage(); } } if (optind == argc || optind + 2 < argc) elfcopy_usage(); infile = argv[optind]; outfile = NULL; if (optind + 1 < argc) outfile = argv[optind + 1]; create_file(ecp, infile, outfile); } static void mcs_main(struct elfcopy *ecp, int argc, char **argv) { struct sec_action *sac; const char *string; int append, delete, compress, name, print; int opt, i; append = delete = compress = name = print = 0; string = NULL; while ((opt = getopt_long(argc, argv, "a:cdhn:pV", mcs_longopts, NULL)) != -1) { switch(opt) { case 'a': append = 1; string = optarg; /* XXX multiple -a not supported */ break; case 'c': compress = 1; break; case 'd': delete = 1; break; case 'n': name = 1; (void)lookup_sec_act(ecp, optarg, 1); break; case 'p': print = 1; break; case 'V': print_version(); break; case 'h': default: mcs_usage(); } } if (optind == argc) mcs_usage(); /* Must specify one operation at least. */ if (!append && !compress && !delete && !print) mcs_usage(); /* * If we are going to delete, ignore other operations. This is * different from the Solaris implementation, which can print * and delete a section at the same time, for example. Also, this * implementation do not respect the order between operations that * user specified, i.e., "mcs -pc a.out" equals to "mcs -cp a.out". */ if (delete) { append = compress = print = 0; ecp->flags |= SEC_REMOVE; } if (append) ecp->flags |= SEC_APPEND; if (compress) ecp->flags |= SEC_COMPRESS; if (print) ecp->flags |= SEC_PRINT; /* .comment is the default section to operate on. */ if (!name) (void)lookup_sec_act(ecp, ".comment", 1); STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { sac->append = append; sac->compress = compress; sac->print = print; sac->remove = delete; sac->string = string; } for (i = optind; i < argc; i++) { /* If only -p is specified, output to /dev/null */ if (print && !append && !compress && !delete) create_file(ecp, argv[i], "/dev/null"); else create_file(ecp, argv[i], NULL); } } static void strip_main(struct elfcopy *ecp, int argc, char **argv) { struct sec_action *sac; const char *outfile; int opt; int i; outfile = NULL; while ((opt = getopt_long(argc, argv, "hI:K:N:o:O:pR:sSdgVxXw", strip_longopts, NULL)) != -1) { switch(opt) { case 'R': sac = lookup_sec_act(ecp, optarg, 1); sac->remove = 1; ecp->flags |= SEC_REMOVE; break; case 's': ecp->strip = STRIP_ALL; break; case 'S': case 'g': case 'd': ecp->strip = STRIP_DEBUG; break; case 'I': /* ignored */ break; case 'K': add_to_symop_list(ecp, optarg, NULL, SYMOP_KEEP); break; case 'N': add_to_symop_list(ecp, optarg, NULL, SYMOP_STRIP); break; case 'o': outfile = optarg; break; case 'O': set_output_target(ecp, optarg); break; case 'p': ecp->flags |= PRESERVE_DATE; break; case 'V': print_version(); break; case 'w': ecp->flags |= WILDCARD; break; case 'x': ecp->flags |= DISCARD_LOCAL; break; case 'X': ecp->flags |= DISCARD_LLABEL; break; case ECP_ONLY_DEBUG: ecp->strip = STRIP_NONDEBUG; break; case ECP_STRIP_UNNEEDED: ecp->strip = STRIP_UNNEEDED; break; case 'h': default: strip_usage(); } } if (ecp->strip == 0 && ((ecp->flags & DISCARD_LOCAL) == 0) && ((ecp->flags & DISCARD_LLABEL) == 0) && lookup_symop_list(ecp, NULL, SYMOP_STRIP) == NULL) ecp->strip = STRIP_ALL; if (optind == argc) strip_usage(); for (i = optind; i < argc; i++) create_file(ecp, argv[i], outfile); } static void parse_sec_flags(struct sec_action *sac, char *s) { const char *flag; int found, i; for (flag = strtok(s, ","); flag; flag = strtok(NULL, ",")) { found = 0; for (i = 0; sec_flags[i].name != NULL; i++) if (strcasecmp(sec_flags[i].name, flag) == 0) { sac->flags |= sec_flags[i].value; found = 1; break; } if (!found) errx(EXIT_FAILURE, "unrecognized section flag %s", flag); } } static void parse_sec_address_op(struct elfcopy *ecp, int optnum, const char *optname, char *s) { struct sec_action *sac; const char *name; char *v; char op; name = v = s; do { v++; } while (*v != '\0' && *v != '=' && *v != '+' && *v != '-'); if (*v == '\0' || *(v + 1) == '\0') errx(EXIT_FAILURE, "invalid format for %s", optname); op = *v; *v++ = '\0'; sac = lookup_sec_act(ecp, name, 1); switch (op) { case '=': if (optnum == ECP_CHANGE_SEC_LMA || optnum == ECP_CHANGE_SEC_ADDR) { sac->setlma = 1; sac->lma = (uint64_t) strtoull(v, NULL, 0); } if (optnum == ECP_CHANGE_SEC_VMA || optnum == ECP_CHANGE_SEC_ADDR) { sac->setvma = 1; sac->vma = (uint64_t) strtoull(v, NULL, 0); } break; case '+': if (optnum == ECP_CHANGE_SEC_LMA || optnum == ECP_CHANGE_SEC_ADDR) sac->lma_adjust = (int64_t) strtoll(v, NULL, 0); if (optnum == ECP_CHANGE_SEC_VMA || optnum == ECP_CHANGE_SEC_ADDR) sac->vma_adjust = (int64_t) strtoll(v, NULL, 0); break; case '-': if (optnum == ECP_CHANGE_SEC_LMA || optnum == ECP_CHANGE_SEC_ADDR) sac->lma_adjust = (int64_t) -strtoll(v, NULL, 0); if (optnum == ECP_CHANGE_SEC_VMA || optnum == ECP_CHANGE_SEC_ADDR) sac->vma_adjust = (int64_t) -strtoll(v, NULL, 0); break; default: break; } } static void parse_symlist_file(struct elfcopy *ecp, const char *fn, unsigned int op) { struct symfile *sf; struct stat sb; FILE *fp; char *data, *p, *line, *end, *e, *n; if (stat(fn, &sb) == -1) err(EXIT_FAILURE, "stat %s failed", fn); /* Check if we already read and processed this file. */ STAILQ_FOREACH(sf, &ecp->v_symfile, symfile_list) { if (sf->dev == sb.st_dev && sf->ino == sb.st_ino) goto process_symfile; } if ((fp = fopen(fn, "r")) == NULL) err(EXIT_FAILURE, "can not open %s", fn); if ((data = malloc(sb.st_size + 1)) == NULL) err(EXIT_FAILURE, "malloc failed"); if (fread(data, 1, sb.st_size, fp) == 0 || ferror(fp)) err(EXIT_FAILURE, "fread failed"); fclose(fp); data[sb.st_size] = '\0'; if ((sf = calloc(1, sizeof(*sf))) == NULL) err(EXIT_FAILURE, "malloc failed"); sf->dev = sb.st_dev; sf->ino = sb.st_ino; sf->size = sb.st_size + 1; sf->data = data; process_symfile: /* * Basically what we do here is to convert EOL to '\0', and remove * leading and trailing whitespaces for each line. */ end = sf->data + sf->size; line = NULL; for(p = sf->data; p < end; p++) { if ((*p == '\t' || *p == ' ') && line == NULL) continue; if (*p == '\r' || *p == '\n' || *p == '\0') { *p = '\0'; if (line == NULL) continue; /* Skip comment. */ if (*line == '#') { line = NULL; continue; } e = p - 1; while(e != line && (*e == '\t' || *e == ' ')) *e-- = '\0'; if (op != SYMOP_REDEF) add_to_symop_list(ecp, line, NULL, op); else { if (strlen(line) < 3) errx(EXIT_FAILURE, "illegal format for" " --redefine-sym"); for(n = line + 1; n < e; n++) { if (*n == ' ' || *n == '\t') { while(*n == ' ' || *n == '\t') *n++ = '\0'; break; } } if (n >= e) errx(EXIT_FAILURE, "illegal format for" " --redefine-sym"); add_to_symop_list(ecp, line, n, op); } line = NULL; continue; } if (line == NULL) line = p; } } static void set_input_target(struct elfcopy *ecp, const char *target_name) { Elftc_Bfd_Target *tgt; if ((tgt = elftc_bfd_find_target(target_name)) == NULL) errx(EXIT_FAILURE, "%s: invalid target name", target_name); ecp->itf = elftc_bfd_target_flavor(tgt); } static void set_output_target(struct elfcopy *ecp, const char *target_name) { Elftc_Bfd_Target *tgt; if ((tgt = elftc_bfd_find_target(target_name)) == NULL) errx(EXIT_FAILURE, "%s: invalid target name", target_name); ecp->otf = elftc_bfd_target_flavor(tgt); if (ecp->otf == ETF_ELF) { ecp->oec = elftc_bfd_target_class(tgt); ecp->oed = elftc_bfd_target_byteorder(tgt); ecp->oem = elftc_bfd_target_machine(tgt); } ecp->otgt = target_name; } static void set_osabi(struct elfcopy *ecp, const char *abi) { int i, found; found = 0; for (i = 0; osabis[i].name != NULL; i++) if (strcasecmp(osabis[i].name, abi) == 0) { ecp->abi = osabis[i].abi; found = 1; break; } if (!found) errx(EXIT_FAILURE, "unrecognized OSABI %s", abi); } #define ELFCOPY_USAGE_MESSAGE "\ Usage: %s [options] infile [outfile]\n\ Transform an ELF object.\n\n\ Options:\n\ -d | -g | --strip-debug Remove debugging information from the output.\n\ -j SECTION | --only-section=SECTION\n\ Copy only the named section to the output.\n\ -p | --preserve-dates Preserve access and modification times.\n\ -w | --wildcard Use shell-style patterns to name symbols.\n\ -x | --discard-all Do not copy non-globals to the output.\n\ -I FORMAT | --input-target=FORMAT\n\ (Accepted but ignored).\n\ -K SYM | --keep-symbol=SYM Copy symbol SYM to the output.\n\ -L SYM | --localize-symbol=SYM\n\ Make symbol SYM local to the output file.\n\ -N SYM | --strip-symbol=SYM Do not copy symbol SYM to the output.\n\ -R NAME | --remove-section=NAME\n\ Remove the named section.\n\ -S | --strip-all Remove all symbol and relocation information\n\ from the output.\n\ -V | --version Print a version identifier and exit.\n\ -W SYM | --weaken-symbol=SYM Mark symbol SYM as weak in the output.\n\ -X | --discard-locals Do not copy compiler generated symbols to\n\ the output.\n\ --add-section NAME=FILE Add the contents of FILE to the ELF object as\n\ a new section named NAME.\n\ --adjust-section-vma SECTION{=,+,-}VAL | \\\n\ --change-section-address SECTION{=,+,-}VAL\n\ Set or adjust the VMA and the LMA of the\n\ named section by VAL.\n\ --adjust-start=INCR | --change-start=INCR\n\ Add INCR to the start address for the ELF\n\ object.\n\ --adjust-vma=INCR | --change-addresses=INCR\n\ Increase the VMA and LMA of all sections by\n\ INCR.\n\ --adjust-warning | --change-warnings\n\ Issue warnings for non-existent sections.\n\ --change-section-lma SECTION{=,+,-}VAL\n\ Set or adjust the LMA address of the named\n\ section by VAL.\n\ --change-section-vma SECTION{=,+,-}VAL\n\ Set or adjust the VMA address of the named\n\ section by VAL.\n\ --gap-fill=VAL Fill the gaps between sections with bytes\n\ of value VAL.\n\ + --localize-hidden Make all hidden symbols local to the output\n\ + file.\n\ --no-adjust-warning| --no-change-warnings\n\ Do not issue warnings for non-existent\n\ sections.\n\ --only-keep-debug Copy only debugging information.\n\ --output-target=FORMAT Use the specified format for the output.\n\ --pad-to=ADDRESS Pad the output object upto the given address.\n\ --prefix-alloc-sections=STRING\n\ Prefix the section names of all the allocated\n\ sections with STRING.\n\ --prefix-sections=STRING Prefix the section names of all the sections\n\ with STRING.\n\ --prefix-symbols=STRING Prefix the symbol names of all the symbols\n\ with STRING.\n\ --rename-section OLDNAME=NEWNAME[,FLAGS]\n\ Rename and optionally change section flags.\n\ --set-section-flags SECTION=FLAGS\n\ Set section flags for the named section.\n\ Supported flags are: 'alloc', 'code',\n\ 'contents', 'data', 'debug', 'load',\n\ 'noload', 'readonly', 'rom', and 'shared'.\n\ --set-start=ADDRESS Set the start address of the ELF object.\n\ --srec-forceS3 Only generate S3 S-Records.\n\ --srec-len=LEN Set the maximum length of a S-Record line.\n\ --strip-unneeded Do not copy relocation information.\n" static void elfcopy_usage(void) { (void) fprintf(stderr, ELFCOPY_USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } #define MCS_USAGE_MESSAGE "\ Usage: %s [options] file...\n\ Manipulate the comment section in an ELF object.\n\n\ Options:\n\ -a STRING Append 'STRING' to the comment section.\n\ -c Remove duplicate entries from the comment section.\n\ -d Delete the comment section.\n\ -h | --help Print a help message and exit.\n\ -n NAME Operate on the ELF section with name 'NAME'.\n\ -p Print the contents of the comment section.\n\ -V | --version Print a version identifier and exit.\n" static void mcs_usage(void) { (void) fprintf(stderr, MCS_USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } #define STRIP_USAGE_MESSAGE "\ Usage: %s [options] file...\n\ Discard information from ELF objects.\n\n\ Options:\n\ -d | -g | -S | --strip-debug Remove debugging symbols.\n\ -h | --help Print a help message.\n\ --only-keep-debug Keep debugging information only.\n\ -p | --preserve-dates Preserve access and modification times.\n\ -s | --strip-all Remove all symbols.\n\ --strip-unneeded Remove symbols not needed for relocation\n\ processing.\n\ -w | --wildcard Use shell-style patterns to name symbols.\n\ -x | --discard-all Discard all non-global symbols.\n\ -I TGT| --input-target=TGT (Accepted, but ignored).\n\ -K SYM | --keep-symbol=SYM Keep symbol 'SYM' in the output.\n\ -N SYM | --strip-symbol=SYM Remove symbol 'SYM' from the output.\n\ -O TGT | --output-target=TGT Set the output file format to 'TGT'.\n\ -R SEC | --remove-section=SEC Remove the section named 'SEC'.\n\ -V | --version Print a version identifier and exit.\n\ -X | --discard-locals Remove compiler-generated local symbols.\n" static void strip_usage(void) { (void) fprintf(stderr, STRIP_USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } static void print_version(void) { (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(EXIT_SUCCESS); } int main(int argc, char **argv) { struct elfcopy *ecp; if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization failed: %s", elf_errmsg(-1)); ecp = calloc(1, sizeof(*ecp)); if (ecp == NULL) err(EXIT_FAILURE, "calloc failed"); memset(ecp, 0, sizeof(*ecp)); ecp->itf = ecp->otf = ETF_ELF; ecp->iec = ecp->oec = ELFCLASSNONE; ecp->oed = ELFDATANONE; ecp->abi = -1; /* There is always an empty section. */ ecp->nos = 1; ecp->fill = 0; STAILQ_INIT(&ecp->v_seg); STAILQ_INIT(&ecp->v_sac); STAILQ_INIT(&ecp->v_sadd); STAILQ_INIT(&ecp->v_symop); STAILQ_INIT(&ecp->v_symfile); STAILQ_INIT(&ecp->v_arobj); TAILQ_INIT(&ecp->v_sec); if ((ecp->progname = ELFTC_GETPROGNAME()) == NULL) ecp->progname = "elfcopy"; if (strcmp(ecp->progname, "strip") == 0) strip_main(ecp, argc, argv); else if (strcmp(ecp->progname, "mcs") == 0) mcs_main(ecp, argc, argv); else elfcopy_main(ecp, argc, argv); free_sec_add(ecp); free_sec_act(ecp); free(ecp); exit(EXIT_SUCCESS); } Index: head/contrib/elftoolchain/elfcopy/sections.c =================================================================== --- head/contrib/elftoolchain/elfcopy/sections.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/sections.c (revision 280932) @@ -1,1550 +1,1565 @@ /*- * Copyright (c) 2007-2011,2014 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: sections.c 3150 2015-02-15 19:07:46Z emaste $"); +ELFTC_VCSID("$Id: sections.c 3174 2015-03-27 17:13:41Z emaste $"); static void add_gnu_debuglink(struct elfcopy *ecp); static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc); static void check_section_rename(struct elfcopy *ecp, struct section *s); static void filter_reloc(struct elfcopy *ecp, struct section *s); static int get_section_flags(struct elfcopy *ecp, const char *name); static void insert_sections(struct elfcopy *ecp); static void insert_to_strtab(struct section *t, const char *s); static int is_append_section(struct elfcopy *ecp, const char *name); static int is_compress_section(struct elfcopy *ecp, const char *name); static int is_debug_section(const char *name); +static int is_dwo_section(const char *name); static int is_modify_section(struct elfcopy *ecp, const char *name); static int is_print_section(struct elfcopy *ecp, const char *name); static int lookup_string(struct section *t, const char *s); static void modify_section(struct elfcopy *ecp, struct section *s); static void pad_section(struct elfcopy *ecp, struct section *s); static void print_data(const char *d, size_t sz); static void print_section(struct section *s); static void *read_section(struct section *s, size_t *size); static void update_reloc(struct elfcopy *ecp, struct section *s); int is_remove_section(struct elfcopy *ecp, const char *name) { /* Always keep section name table */ if (strcmp(name, ".shstrtab") == 0) return 0; if (strcmp(name, ".symtab") == 0 || strcmp(name, ".strtab") == 0) { if (ecp->strip == STRIP_ALL && lookup_symop_list( ecp, NULL, SYMOP_KEEP) == NULL) return (1); else return (0); } + if (ecp->strip == STRIP_DWO && is_dwo_section(name)) + return (1); + if (ecp->strip == STRIP_NONDWO && !is_dwo_section(name)) + return (1); + if (is_debug_section(name)) { if (ecp->strip == STRIP_ALL || ecp->strip == STRIP_DEBUG || ecp->strip == STRIP_UNNEEDED || (ecp->flags & DISCARD_LOCAL)) return (1); if (ecp->strip == STRIP_NONDEBUG) return (0); } if ((ecp->flags & SEC_REMOVE) || (ecp->flags & SEC_COPY)) { struct sec_action *sac; sac = lookup_sec_act(ecp, name, 0); if ((ecp->flags & SEC_REMOVE) && sac != NULL && sac->remove) return (1); if ((ecp->flags & SEC_COPY) && (sac == NULL || !sac->copy)) return (1); } return (0); } /* * Relocation section needs to be removed if the section it applies to * will be removed. */ int is_remove_reloc_sec(struct elfcopy *ecp, uint32_t sh_info) { const char *name; GElf_Shdr ish; Elf_Scn *is; size_t indx; int elferr; if (elf_getshstrndx(ecp->ein, &indx) == 0) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (sh_info == elf_ndxscn(is)) { if (gelf_getshdr(is, &ish) == NULL) errx(EXIT_FAILURE, "gelf_getshdr failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); if (is_remove_section(ecp, name)) return (1); else return (0); } } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); /* Remove reloc section if we can't find the target section. */ return (1); } static int is_append_section(struct elfcopy *ecp, const char *name) { struct sec_action *sac; sac = lookup_sec_act(ecp, name, 0); if (sac != NULL && sac->append != 0 && sac->string != NULL) return (1); return (0); } static int is_compress_section(struct elfcopy *ecp, const char *name) { struct sec_action *sac; sac = lookup_sec_act(ecp, name, 0); if (sac != NULL && sac->compress != 0) return (1); return (0); } static void check_section_rename(struct elfcopy *ecp, struct section *s) { struct sec_action *sac; char *prefix; size_t namelen; if (s->pseudo) return; sac = lookup_sec_act(ecp, s->name, 0); if (sac != NULL && sac->rename) s->name = sac->newname; if (!strcmp(s->name, ".symtab") || !strcmp(s->name, ".strtab") || !strcmp(s->name, ".shstrtab")) return; prefix = NULL; if (s->loadable && ecp->prefix_alloc != NULL) prefix = ecp->prefix_alloc; else if (ecp->prefix_sec != NULL) prefix = ecp->prefix_sec; if (prefix != NULL) { namelen = strlen(s->name) + strlen(prefix) + 1; if ((s->newname = malloc(namelen)) == NULL) err(EXIT_FAILURE, "malloc failed"); snprintf(s->newname, namelen, "%s%s", prefix, s->name); s->name = s->newname; } } static int get_section_flags(struct elfcopy *ecp, const char *name) { struct sec_action *sac; sac = lookup_sec_act(ecp, name, 0); if (sac != NULL && sac->flags) return sac->flags; return (0); } /* * Determine whether the section are debugging section. * According to libbfd, debugging sections are recognized * only by name. */ static int is_debug_section(const char *name) { const char *dbg_sec[] = { ".debug", ".gnu.linkonce.wi.", ".line", ".stab", NULL }; const char **p; for(p = dbg_sec; *p; p++) { if (strncmp(name, *p, strlen(*p)) == 0) return (1); } + return (0); +} + +static int +is_dwo_section(const char *name) +{ + size_t len; + + if ((len = strlen(name)) > 4 && strcmp(name + len - 4, ".dwo") == 0) + return (1); return (0); } static int is_print_section(struct elfcopy *ecp, const char *name) { struct sec_action *sac; sac = lookup_sec_act(ecp, name, 0); if (sac != NULL && sac->print != 0) return (1); return (0); } static int is_modify_section(struct elfcopy *ecp, const char *name) { if (is_append_section(ecp, name) || is_compress_section(ecp, name)) return (1); return (0); } struct sec_action* lookup_sec_act(struct elfcopy *ecp, const char *name, int add) { struct sec_action *sac; if (name == NULL) return NULL; STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { if (strcmp(name, sac->name) == 0) return sac; } if (add == 0) return NULL; if ((sac = malloc(sizeof(*sac))) == NULL) errx(EXIT_FAILURE, "not enough memory"); memset(sac, 0, sizeof(*sac)); sac->name = name; STAILQ_INSERT_TAIL(&ecp->v_sac, sac, sac_list); return (sac); } void free_sec_act(struct elfcopy *ecp) { struct sec_action *sac, *sac_temp; STAILQ_FOREACH_SAFE(sac, &ecp->v_sac, sac_list, sac_temp) { STAILQ_REMOVE(&ecp->v_sac, sac, sec_action, sac_list); free(sac); } } void insert_to_sec_list(struct elfcopy *ecp, struct section *sec, int tail) { struct section *s; if (!tail) { TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (sec->off < s->off) { TAILQ_INSERT_BEFORE(s, sec, sec_list); goto inc_nos; } } } TAILQ_INSERT_TAIL(&ecp->v_sec, sec, sec_list); inc_nos: if (sec->pseudo == 0) ecp->nos++; } /* * First step of section creation: create scn and internal section * structure, discard sections to be removed. */ void create_scn(struct elfcopy *ecp) { struct section *s; const char *name; Elf_Scn *is; GElf_Shdr ish; size_t indx; uint64_t oldndx, newndx; int elferr, sec_flags; /* * Insert a pseudo section that contains the ELF header * and program header. Used as reference for section offset * or load address adjustment. */ if ((s = calloc(1, sizeof(*s))) == NULL) err(EXIT_FAILURE, "calloc failed"); s->off = 0; s->sz = gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT) + gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); s->align = 1; s->pseudo = 1; s->loadable = add_to_inseg_list(ecp, s); insert_to_sec_list(ecp, s, 0); /* Create internal .shstrtab section. */ init_shstrtab(ecp); if (elf_getshstrndx(ecp->ein, &indx) == 0) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (gelf_getshdr(is, &ish) == NULL) errx(EXIT_FAILURE, "219 gelf_getshdr failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, indx, ish.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); /* Skip sections to be removed. */ if (is_remove_section(ecp, name)) continue; /* * Relocation section need to be remove if the section * it applies will be removed. */ if (ish.sh_type == SHT_REL || ish.sh_type == SHT_RELA) if (ish.sh_info != 0 && is_remove_reloc_sec(ecp, ish.sh_info)) continue; /* * Section groups should be removed if symbol table will * be removed. (section group's signature stored in symbol * table) */ if (ish.sh_type == SHT_GROUP && ecp->strip == STRIP_ALL) continue; /* Get section flags set by user. */ sec_flags = get_section_flags(ecp, name); /* Create internal section object. */ if (strcmp(name, ".shstrtab") != 0) { if ((s = calloc(1, sizeof(*s))) == NULL) err(EXIT_FAILURE, "calloc failed"); s->name = name; s->is = is; s->off = ish.sh_offset; s->sz = ish.sh_size; s->align = ish.sh_addralign; s->type = ish.sh_type; s->vma = ish.sh_addr; /* * Search program headers to determine whether section * is loadable, but if user explicitly set section flags * while neither "load" nor "alloc" is set, we make the * section unloadable. */ if (sec_flags && (sec_flags & (SF_LOAD | SF_ALLOC)) == 0) s->loadable = 0; else s->loadable = add_to_inseg_list(ecp, s); } else { /* Assuming .shstrtab is "unloadable". */ s = ecp->shstrtab; s->off = ish.sh_offset; } oldndx = newndx = SHN_UNDEF; if (strcmp(name, ".symtab") != 0 && strcmp(name, ".strtab") != 0) { if (!strcmp(name, ".shstrtab")) { /* * Add sections specified by --add-section and * gnu debuglink. we want these sections have * smaller index than .shstrtab section. */ if (ecp->debuglink != NULL) add_gnu_debuglink(ecp); if (ecp->flags & SEC_ADD) insert_sections(ecp); } if ((s->os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn failed: %s", elf_errmsg(-1)); if ((newndx = elf_ndxscn(s->os)) == SHN_UNDEF) errx(EXIT_FAILURE, "elf_ndxscn failed: %s", elf_errmsg(-1)); } if ((oldndx = elf_ndxscn(is)) == SHN_UNDEF) errx(EXIT_FAILURE, "elf_ndxscn failed: %s", elf_errmsg(-1)); if (oldndx != SHN_UNDEF && newndx != SHN_UNDEF) ecp->secndx[oldndx] = newndx; /* * If strip action is STRIP_NONDEBUG(only keep debug), * change sections flags of loadable sections to SHF_NOBITS, * and the content of those sections will be ignored. */ if (ecp->strip == STRIP_NONDEBUG && (ish.sh_flags & SHF_ALLOC)) s->type = SHT_NOBITS; check_section_rename(ecp, s); /* create section header based on input object. */ if (strcmp(name, ".symtab") != 0 && strcmp(name, ".strtab") != 0 && strcmp(name, ".shstrtab") != 0) copy_shdr(ecp, s, NULL, 0, sec_flags); if (strcmp(name, ".symtab") == 0) { ecp->flags |= SYMTAB_EXIST; ecp->symtab = s; } if (strcmp(name, ".strtab") == 0) ecp->strtab = s; insert_to_sec_list(ecp, s, 0); } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); } struct section * insert_shtab(struct elfcopy *ecp, int tail) { struct section *s, *shtab; GElf_Ehdr ieh; int nsecs; /* * Treat section header table as a "pseudo" section, insert it * into section list, so later it will get sorted and resynced * just as normal sections. */ if ((shtab = calloc(1, sizeof(*shtab))) == NULL) errx(EXIT_FAILURE, "calloc failed"); if (!tail) { /* * "shoff" of input object is used as a hint for section * resync later. */ if (gelf_getehdr(ecp->ein, &ieh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); shtab->off = ieh.e_shoff; } else shtab->off = 0; /* Calculate number of sections in the output object. */ nsecs = 0; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (!s->pseudo) nsecs++; } /* Remember there is always a null section, so we +1 here. */ shtab->sz = gelf_fsize(ecp->eout, ELF_T_SHDR, nsecs + 1, EV_CURRENT); if (shtab->sz == 0) errx(EXIT_FAILURE, "gelf_fsize() failed: %s", elf_errmsg(-1)); shtab->align = (ecp->oec == ELFCLASS32 ? 4 : 8); shtab->loadable = 0; shtab->pseudo = 1; insert_to_sec_list(ecp, shtab, tail); return (shtab); } void copy_content(struct elfcopy *ecp) { struct section *s; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { /* Skip pseudo section. */ if (s->pseudo) continue; /* Skip special sections. */ if (strcmp(s->name, ".symtab") == 0 || strcmp(s->name, ".strtab") == 0 || strcmp(s->name, ".shstrtab") == 0) continue; /* * If strip action is STRIP_ALL, relocation info need * to be stripped. Skip filtering otherwisw. */ if (ecp->strip == STRIP_ALL && (s->type == SHT_REL || s->type == SHT_RELA)) filter_reloc(ecp, s); if (is_modify_section(ecp, s->name)) modify_section(ecp, s); copy_data(s); /* * If symbol table is modified, relocation info might * need update, as symbol index may have changed. */ if ((ecp->flags & SYMTAB_INTACT) == 0 && (ecp->flags & SYMTAB_EXIST) && (s->type == SHT_REL || s->type == SHT_RELA)) update_reloc(ecp, s); if (is_print_section(ecp, s->name)) print_section(s); } } /* * Filter relocation entries, only keep those entries whose * symbol is in the keep list. */ static void filter_reloc(struct elfcopy *ecp, struct section *s) { const char *name; GElf_Shdr ish; GElf_Rel rel; GElf_Rela rela; Elf32_Rel *rel32; Elf64_Rel *rel64; Elf32_Rela *rela32; Elf64_Rela *rela64; Elf_Data *id; uint64_t cap, n, nrels; int elferr, i; if (gelf_getshdr(s->is, &ish) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* We don't want to touch relocation info for dynamic symbols. */ if ((ecp->flags & SYMTAB_EXIST) == 0) { if (ish.sh_link == 0 || ecp->secndx[ish.sh_link] == 0) { /* * This reloc section applies to the symbol table * that was stripped, so discard whole section. */ s->nocopy = 1; s->sz = 0; } return; } else { /* Symbol table exist, check if index equals. */ if (ish.sh_link != elf_ndxscn(ecp->symtab->is)) return; } #define COPYREL(REL, SZ) do { \ if (nrels == 0) { \ if ((REL##SZ = malloc(cap * \ sizeof(Elf##SZ##_Rel))) == NULL) \ err(EXIT_FAILURE, "malloc failed"); \ } \ if (nrels >= cap) { \ cap *= 2; \ if ((REL##SZ = realloc(REL##SZ, cap * \ sizeof(Elf##SZ##_Rel))) == NULL) \ err(EXIT_FAILURE, "realloc failed"); \ } \ REL##SZ[nrels].r_offset = REL.r_offset; \ REL##SZ[nrels].r_info = REL.r_info; \ if (s->type == SHT_RELA) \ rela##SZ[nrels].r_addend = rela.r_addend; \ nrels++; \ } while (0) nrels = 0; cap = 4; /* keep list is usually small. */ rel32 = NULL; rel64 = NULL; rela32 = NULL; rela64 = NULL; if ((id = elf_getdata(s->is, NULL)) == NULL) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(-1)); n = ish.sh_size / ish.sh_entsize; for(i = 0; (uint64_t)i < n; i++) { if (s->type == SHT_REL) { if (gelf_getrel(id, i, &rel) != &rel) errx(EXIT_FAILURE, "gelf_getrel failed: %s", elf_errmsg(-1)); } else { if (gelf_getrela(id, i, &rela) != &rela) errx(EXIT_FAILURE, "gelf_getrel failed: %s", elf_errmsg(-1)); } name = elf_strptr(ecp->ein, elf_ndxscn(ecp->strtab->is), GELF_R_SYM(rel.r_info)); if (name == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) { if (ecp->oec == ELFCLASS32) { if (s->type == SHT_REL) COPYREL(rel, 32); else COPYREL(rela, 32); } else { if (s->type == SHT_REL) COPYREL(rel, 64); else COPYREL(rela, 64); } } } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(elferr)); if (ecp->oec == ELFCLASS32) { if (s->type == SHT_REL) s->buf = rel32; else s->buf = rela32; } else { if (s->type == SHT_REL) s->buf = rel64; else s->buf = rela64; } s->sz = gelf_fsize(ecp->eout, (s->type == SHT_REL ? ELF_T_REL : ELF_T_RELA), nrels, EV_CURRENT); s->nocopy = 1; } static void update_reloc(struct elfcopy *ecp, struct section *s) { GElf_Shdr osh; GElf_Rel rel; GElf_Rela rela; Elf_Data *od; uint64_t n; int i; #define UPDATEREL(REL) do { \ if (gelf_get##REL(od, i, &REL) != &REL) \ errx(EXIT_FAILURE, "gelf_get##REL failed: %s", \ elf_errmsg(-1)); \ REL.r_info = GELF_R_INFO(ecp->symndx[GELF_R_SYM(REL.r_info)], \ GELF_R_TYPE(REL.r_info)); \ if (!gelf_update_##REL(od, i, &REL)) \ errx(EXIT_FAILURE, "gelf_update_##REL failed: %s", \ elf_errmsg(-1)); \ } while(0) if (s->sz == 0) return; if (gelf_getshdr(s->os, &osh) == NULL) errx(EXIT_FAILURE, "gelf_getehdr() failed: %s", elf_errmsg(-1)); /* Only process .symtab reloc info. */ if (osh.sh_link != elf_ndxscn(ecp->symtab->is)) return; if ((od = elf_getdata(s->os, NULL)) == NULL) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(-1)); n = osh.sh_size / osh.sh_entsize; for(i = 0; (uint64_t)i < n; i++) { if (s->type == SHT_REL) UPDATEREL(rel); else UPDATEREL(rela); } } static void pad_section(struct elfcopy *ecp, struct section *s) { GElf_Shdr osh; Elf_Data *od; if (s == NULL || s->pad_sz == 0) return; if ((s->pad = malloc(s->pad_sz)) == NULL) err(EXIT_FAILURE, "malloc failed"); memset(s->pad, ecp->fill, s->pad_sz); /* Create a new Elf_Data to contain the padding bytes. */ if ((od = elf_newdata(s->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s", elf_errmsg(-1)); od->d_align = 1; od->d_off = s->sz; od->d_buf = s->pad; od->d_type = ELF_T_BYTE; od->d_size = s->pad_sz; od->d_version = EV_CURRENT; /* Update section header. */ if (gelf_getshdr(s->os, &osh) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); osh.sh_size = s->sz + s->pad_sz; if (!gelf_update_shdr(s->os, &osh)) errx(EXIT_FAILURE, "elf_update_shdr failed: %s", elf_errmsg(-1)); } void resync_sections(struct elfcopy *ecp) { struct section *s, *ps; GElf_Shdr osh; uint64_t off; int first; ps = NULL; first = 1; off = 0; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (first) { off = s->off; first = 0; } /* * Ignore TLS sections with load address 0 and without * content. We don't need to adjust their file offset or * VMA, only the size matters. */ if (s->seg_tls != NULL && s->type == SHT_NOBITS && s->off == 0) continue; /* Align section offset. */ if (s->align == 0) s->align = 1; if (off <= s->off) { if (!s->loadable) s->off = roundup(off, s->align); } else { if (s->loadable) warnx("moving loadable section %s, " "is this intentional?", s->name); s->off = roundup(off, s->align); } /* Calculate next section offset. */ off = s->off; if (s->pseudo || (s->type != SHT_NOBITS && s->type != SHT_NULL)) off += s->sz; if (s->pseudo) { ps = NULL; continue; } /* Count padding bytes added through --pad-to. */ if (s->pad_sz > 0) off += s->pad_sz; /* Update section header accordingly. */ if (gelf_getshdr(s->os, &osh) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); osh.sh_addr = s->vma; osh.sh_offset = s->off; osh.sh_size = s->sz; if (!gelf_update_shdr(s->os, &osh)) errx(EXIT_FAILURE, "elf_update_shdr failed: %s", elf_errmsg(-1)); /* Add padding for previous section, if need. */ if (ps != NULL) { if (ps->pad_sz > 0) { /* Apply padding added by --pad-to. */ pad_section(ecp, ps); } else if ((ecp->flags & GAP_FILL) && (ps->off + ps->sz < s->off)) { /* * Fill the gap between sections by padding * the section with lower address. */ ps->pad_sz = s->off - (ps->off + ps->sz); pad_section(ecp, ps); } } ps = s; } /* Pad the last section, if need. */ if (ps != NULL && ps->pad_sz > 0) pad_section(ecp, ps); } static void modify_section(struct elfcopy *ecp, struct section *s) { struct sec_action *sac; size_t srcsz, dstsz, p, len; char *b, *c, *d, *src, *end; int dupe; src = read_section(s, &srcsz); if (src == NULL || srcsz == 0) { /* For empty section, we proceed if we need to append. */ if (!is_append_section(ecp, s->name)) return; } /* Allocate buffer needed for new section data. */ dstsz = srcsz; if (is_append_section(ecp, s->name)) { sac = lookup_sec_act(ecp, s->name, 0); dstsz += strlen(sac->string) + 1; } if ((b = malloc(dstsz)) == NULL) err(EXIT_FAILURE, "malloc failed"); s->buf = b; /* Compress section. */ p = 0; if (is_compress_section(ecp, s->name)) { end = src + srcsz; for(c = src; c < end;) { len = 0; while(c + len < end && c[len] != '\0') len++; if (c + len == end) { /* XXX should we warn here? */ strncpy(&b[p], c, len); p += len; break; } dupe = 0; for (d = b; d < b + p; ) { if (strcmp(d, c) == 0) { dupe = 1; break; } d += strlen(d) + 1; } if (!dupe) { strncpy(&b[p], c, len); b[p + len] = '\0'; p += len + 1; } c += len + 1; } } else { memcpy(b, src, srcsz); p += srcsz; } /* Append section. */ if (is_append_section(ecp, s->name)) { sac = lookup_sec_act(ecp, s->name, 0); len = strlen(sac->string); strncpy(&b[p], sac->string, len); b[p + len] = '\0'; p += len + 1; } s->sz = p; s->nocopy = 1; } static void print_data(const char *d, size_t sz) { const char *c; for (c = d; c < d + sz; c++) { if (*c == '\0') putchar('\n'); else putchar(*c); } } static void print_section(struct section *s) { Elf_Data *id; int elferr; if (s->buf != NULL && s->sz > 0) { print_data(s->buf, s->sz); } else { id = NULL; while ((id = elf_getdata(s->is, id)) != NULL) print_data(id->d_buf, id->d_size); elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(elferr)); } putchar('\n'); } static void * read_section(struct section *s, size_t *size) { Elf_Data *id; char *b; size_t sz; int elferr; sz = 0; b = NULL; id = NULL; while ((id = elf_getdata(s->is, id)) != NULL) { if (b == NULL) b = malloc(id->d_size); else b = malloc(sz + id->d_size); if (b == NULL) err(EXIT_FAILURE, "malloc or realloc failed"); memcpy(&b[sz], id->d_buf, id->d_size); sz += id->d_size; } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(elferr)); *size = sz; return (b); } void copy_shdr(struct elfcopy *ecp, struct section *s, const char *name, int copy, int sec_flags) { GElf_Shdr ish, osh; if (gelf_getshdr(s->is, &ish) == NULL) errx(EXIT_FAILURE, "526 gelf_getshdr() failed: %s", elf_errmsg(-1)); if (gelf_getshdr(s->os, &osh) == NULL) errx(EXIT_FAILURE, "529 gelf_getshdr() failed: %s", elf_errmsg(-1)); if (copy) (void) memcpy(&osh, &ish, sizeof(ish)); else { osh.sh_type = s->type; osh.sh_addr = s->vma; osh.sh_offset = s->off; osh.sh_size = s->sz; osh.sh_link = ish.sh_link; osh.sh_info = ish.sh_info; osh.sh_addralign = s->align; osh.sh_entsize = ish.sh_entsize; if (sec_flags) { osh.sh_flags = 0; if (sec_flags & SF_ALLOC) { osh.sh_flags |= SHF_ALLOC; if (!s->loadable) warnx("set SHF_ALLOC flag for " "unloadable section %s", s->name); } if ((sec_flags & SF_READONLY) == 0) osh.sh_flags |= SHF_WRITE; if (sec_flags & SF_CODE) osh.sh_flags |= SHF_EXECINSTR; } else osh.sh_flags = ish.sh_flags; } if (name == NULL) add_to_shstrtab(ecp, s->name); else add_to_shstrtab(ecp, name); if (!gelf_update_shdr(s->os, &osh)) errx(EXIT_FAILURE, "elf_update_shdr failed: %s", elf_errmsg(-1)); } void copy_data(struct section *s) { Elf_Data *id, *od; int elferr; if (s->nocopy && s->buf == NULL) return; if ((id = elf_getdata(s->is, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata() failed: %s", elf_errmsg(elferr)); return; } if ((od = elf_newdata(s->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s", elf_errmsg(-1)); if (s->nocopy) { /* Use s->buf as content if s->nocopy is set. */ od->d_align = id->d_align; od->d_off = 0; od->d_buf = s->buf; od->d_type = id->d_type; od->d_size = s->sz; od->d_version = id->d_version; } else { od->d_align = id->d_align; od->d_off = id->d_off; od->d_buf = id->d_buf; od->d_type = id->d_type; od->d_size = id->d_size; od->d_version = id->d_version; } /* * Alignment Fixup. libelf does not allow the alignment for * Elf_Data descriptor to be set to 0. In this case we workaround * it by setting the alignment to 1. * * According to the ELF ABI, alignment 0 and 1 has the same * meaning: the section has no alignment constraints. */ if (od->d_align == 0) od->d_align = 1; } struct section * create_external_section(struct elfcopy *ecp, const char *name, char *newname, void *buf, uint64_t size, uint64_t off, uint64_t stype, Elf_Type dtype, uint64_t flags, uint64_t align, uint64_t vma, int loadable) { struct section *s; Elf_Scn *os; Elf_Data *od; GElf_Shdr osh; if ((os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn() failed: %s", elf_errmsg(-1)); if ((s = calloc(1, sizeof(*s))) == NULL) err(EXIT_FAILURE, "calloc failed"); s->name = name; s->newname = newname; /* needs to be free()'ed */ s->off = off; s->sz = size; s->vma = vma; s->align = align; s->loadable = loadable; s->is = NULL; s->os = os; s->type = stype; s->nocopy = 1; insert_to_sec_list(ecp, s, 1); if (gelf_getshdr(os, &osh) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); osh.sh_flags = flags; osh.sh_type = s->type; osh.sh_addr = s->vma; osh.sh_addralign = s->align; if (!gelf_update_shdr(os, &osh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); add_to_shstrtab(ecp, name); if (buf != NULL && size != 0) { if ((od = elf_newdata(os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s", elf_errmsg(-1)); od->d_align = align; od->d_off = 0; od->d_buf = buf; od->d_size = size; od->d_type = dtype; od->d_version = EV_CURRENT; } /* * Clear SYMTAB_INTACT, as we probably need to update/add new * STT_SECTION symbols into the symbol table. */ ecp->flags &= ~SYMTAB_INTACT; return (s); } /* * Insert sections specified by --add-section to the end of section list. */ static void insert_sections(struct elfcopy *ecp) { struct sec_add *sa; struct section *s; size_t off; /* Put these sections in the end of current list. */ off = 0; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->type != SHT_NOBITS && s->type != SHT_NULL) off = s->off + s->sz; else off = s->off; } STAILQ_FOREACH(sa, &ecp->v_sadd, sadd_list) { /* TODO: Add section header vma/lma, flag changes here */ (void) create_external_section(ecp, sa->name, NULL, sa->content, sa->size, off, SHT_PROGBITS, ELF_T_BYTE, 0, 1, 0, 0); } } void add_to_shstrtab(struct elfcopy *ecp, const char *name) { struct section *s; s = ecp->shstrtab; insert_to_strtab(s, name); } void update_shdr(struct elfcopy *ecp, int update_link) { struct section *s; GElf_Shdr osh; int elferr; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->pseudo) continue; if (gelf_getshdr(s->os, &osh) == NULL) errx(EXIT_FAILURE, "668 gelf_getshdr failed: %s", elf_errmsg(-1)); /* Find section name in string table and set sh_name. */ osh.sh_name = lookup_string(ecp->shstrtab, s->name); /* * sh_link needs to be updated, since the index of the * linked section might have changed. */ if (update_link && osh.sh_link != 0) osh.sh_link = ecp->secndx[osh.sh_link]; /* * sh_info of relocation section links to the section to which * its relocation info applies. So it may need update as well. */ if ((s->type == SHT_REL || s->type == SHT_RELA) && osh.sh_info != 0) osh.sh_info = ecp->secndx[osh.sh_info]; if (!gelf_update_shdr(s->os, &osh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); } void init_shstrtab(struct elfcopy *ecp) { struct section *s; if ((ecp->shstrtab = calloc(1, sizeof(*ecp->shstrtab))) == NULL) err(EXIT_FAILURE, "calloc failed"); s = ecp->shstrtab; s->name = ".shstrtab"; s->is = NULL; s->sz = 0; s->align = 1; s->loadable = 0; s->type = SHT_STRTAB; s->vma = 0; insert_to_strtab(s, ""); insert_to_strtab(s, ".symtab"); insert_to_strtab(s, ".strtab"); insert_to_strtab(s, ".shstrtab"); } void set_shstrtab(struct elfcopy *ecp) { struct section *s; Elf_Data *data; GElf_Shdr sh; s = ecp->shstrtab; if (gelf_getshdr(s->os, &sh) == NULL) errx(EXIT_FAILURE, "692 gelf_getshdr() failed: %s", elf_errmsg(-1)); sh.sh_addr = 0; sh.sh_addralign = 1; sh.sh_offset = s->off; sh.sh_type = SHT_STRTAB; sh.sh_flags = 0; sh.sh_entsize = 0; sh.sh_info = 0; sh.sh_link = 0; if ((data = elf_newdata(s->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s", elf_errmsg(-1)); /* * If we don't have a symbol table, skip those a few bytes * which are reserved for this in the beginning of shstrtab. */ if (!(ecp->flags & SYMTAB_EXIST)) { s->sz -= sizeof(".symtab\0.strtab"); memmove(s->buf, (char *)s->buf + sizeof(".symtab\0.strtab"), s->sz); } sh.sh_size = s->sz; if (!gelf_update_shdr(s->os, &sh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); data->d_align = 1; data->d_buf = s->buf; data->d_size = s->sz; data->d_off = 0; data->d_type = ELF_T_BYTE; data->d_version = EV_CURRENT; if (!elf_setshstrndx(ecp->eout, elf_ndxscn(s->os))) errx(EXIT_FAILURE, "elf_setshstrndx() failed: %s", elf_errmsg(-1)); } void add_section(struct elfcopy *ecp, const char *arg) { struct sec_add *sa; struct stat sb; const char *s, *fn; FILE *fp; int len; if ((s = strchr(arg, '=')) == NULL) errx(EXIT_FAILURE, "illegal format for --add-section option"); if ((sa = malloc(sizeof(*sa))) == NULL) err(EXIT_FAILURE, "malloc failed"); len = s - arg; if ((sa->name = malloc(len + 1)) == NULL) err(EXIT_FAILURE, "malloc failed"); strncpy(sa->name, arg, len); sa->name[len] = '\0'; fn = s + 1; if (stat(fn, &sb) == -1) err(EXIT_FAILURE, "stat failed"); sa->size = sb.st_size; if ((sa->content = malloc(sa->size)) == NULL) err(EXIT_FAILURE, "malloc failed"); if ((fp = fopen(fn, "r")) == NULL) err(EXIT_FAILURE, "can not open %s", fn); if (fread(sa->content, 1, sa->size, fp) == 0 || ferror(fp)) err(EXIT_FAILURE, "fread failed"); fclose(fp); STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); ecp->flags |= SEC_ADD; } void free_sec_add(struct elfcopy *ecp) { struct sec_add *sa, *sa_temp; STAILQ_FOREACH_SAFE(sa, &ecp->v_sadd, sadd_list, sa_temp) { STAILQ_REMOVE(&ecp->v_sadd, sa, sec_add, sadd_list); free(sa->name); free(sa->content); free(sa); } } static void add_gnu_debuglink(struct elfcopy *ecp) { struct sec_add *sa; struct stat sb; FILE *fp; char *fnbase, *buf; int crc_off; int crc; if (ecp->debuglink == NULL) return; /* Read debug file content. */ if ((sa = malloc(sizeof(*sa))) == NULL) err(EXIT_FAILURE, "malloc failed"); if ((sa->name = strdup(".gnu_debuglink")) == NULL) err(EXIT_FAILURE, "strdup failed"); if (stat(ecp->debuglink, &sb) == -1) err(EXIT_FAILURE, "stat failed"); if ((buf = malloc(sb.st_size)) == NULL) err(EXIT_FAILURE, "malloc failed"); if ((fp = fopen(ecp->debuglink, "r")) == NULL) err(EXIT_FAILURE, "can not open %s", ecp->debuglink); if (fread(buf, 1, sb.st_size, fp) == 0 || ferror(fp)) err(EXIT_FAILURE, "fread failed"); fclose(fp); /* Calculate crc checksum. */ crc = calc_crc32(buf, sb.st_size, 0xFFFFFFFF); free(buf); /* Calculate section size and the offset to store crc checksum. */ if ((fnbase = basename(ecp->debuglink)) == NULL) err(EXIT_FAILURE, "basename failed"); crc_off = roundup(strlen(fnbase) + 1, 4); sa->size = crc_off + 4; /* Section content. */ if ((sa->content = calloc(1, sa->size)) == NULL) err(EXIT_FAILURE, "malloc failed"); strncpy(sa->content, fnbase, strlen(fnbase)); if (ecp->oed == ELFDATA2LSB) { sa->content[crc_off] = crc & 0xFF; sa->content[crc_off + 1] = (crc >> 8) & 0xFF; sa->content[crc_off + 2] = (crc >> 16) & 0xFF; sa->content[crc_off + 3] = crc >> 24; } else { sa->content[crc_off] = crc >> 24; sa->content[crc_off + 1] = (crc >> 16) & 0xFF; sa->content[crc_off + 2] = (crc >> 8) & 0xFF; sa->content[crc_off + 3] = crc & 0xFF; } STAILQ_INSERT_TAIL(&ecp->v_sadd, sa, sadd_list); ecp->flags |= SEC_ADD; } static void insert_to_strtab(struct section *t, const char *s) { const char *r; char *b, *c; size_t len, slen; int append; if (t->sz == 0) { t->cap = 512; if ((t->buf = malloc(t->cap)) == NULL) err(EXIT_FAILURE, "malloc failed"); } slen = strlen(s); append = 0; b = t->buf; for (c = b; c < b + t->sz;) { len = strlen(c); if (!append && len >= slen) { r = c + (len - slen); if (strcmp(r, s) == 0) return; } else if (len < slen && len != 0) { r = s + (slen - len); if (strcmp(c, r) == 0) { t->sz -= len + 1; memmove(c, c + len + 1, t->sz - (c - b)); append = 1; continue; } } c += len + 1; } while (t->sz + slen + 1 >= t->cap) { t->cap *= 2; if ((t->buf = realloc(t->buf, t->cap)) == NULL) err(EXIT_FAILURE, "realloc failed"); } b = t->buf; strncpy(&b[t->sz], s, slen); b[t->sz + slen] = '\0'; t->sz += slen + 1; } static int lookup_string(struct section *t, const char *s) { const char *b, *c, *r; size_t len, slen; slen = strlen(s); b = t->buf; for (c = b; c < b + t->sz;) { len = strlen(c); if (len >= slen) { r = c + (len - slen); if (strcmp(r, s) == 0) return (r - b); } c += len + 1; } return (-1); } static uint32_t crctable[256] = { 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L, 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L, 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L, 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L, 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL, 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L, 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL, 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL, 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L, 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L, 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L, 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L, 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL, 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L, 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL, 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL, 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L, 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L, 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L, 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L, 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL, 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L, 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL, 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL, 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L, 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L, 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L, 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L, 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL, 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L, 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL, 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL }; static uint32_t calc_crc32(const char *p, size_t len, uint32_t crc) { uint32_t i; for (i = 0; i < len; i++) { crc = crctable[(crc ^ *p++) & 0xFFL] ^ (crc >> 8); } return (crc ^ 0xFFFFFFFF); } Index: head/contrib/elftoolchain/elfcopy/segments.c =================================================================== --- head/contrib/elftoolchain/elfcopy/segments.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/segments.c (revision 280932) @@ -1,496 +1,495 @@ /*- * Copyright (c) 2007-2010,2012 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: segments.c 3134 2014-12-23 10:43:59Z kaiwang27 $"); +ELFTC_VCSID("$Id: segments.c 3177 2015-03-30 18:19:41Z emaste $"); static void insert_to_inseg_list(struct segment *seg, struct section *sec); /* * elfcopy's segment handling is relatively simpler and less powerful than * libbfd. Program headers are modified or copied from input to output objects, * but never re-generated. As a result, if the input object has incorrect * program headers, the output object's program headers will remain incorrect * or become even worse. */ /* * Check whether a section is "loadable". If so, add it to the * corresponding segment list(s) and return 1. */ int add_to_inseg_list(struct elfcopy *ecp, struct section *s) { struct segment *seg; int loadable; if (ecp->ophnum == 0) return (0); /* * Segment is a different view of an ELF object. One segment can * contain one or more sections, and one section can be included * in one or more segments, or not included in any segment at all. * We call those sections which can be found in one or more segments * "loadable" sections, and call the rest "unloadable" sections. * We keep track of "loadable" sections in their containing * segment(s)' v_sec queue. These information are later used to * recalculate the extents of segments, when sections are removed, * for example. */ loadable = 0; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (s->off < seg->off || (s->vma < seg->addr && !s->pseudo)) continue; if (s->off + s->sz > seg->off + seg->fsz && s->type != SHT_NOBITS) continue; if (s->off + s->sz > seg->off + seg->msz) continue; if (s->vma + s->sz > seg->addr + seg->msz) continue; insert_to_inseg_list(seg, s); if (seg->type == PT_LOAD) s->seg = seg; else if (seg->type == PT_TLS) s->seg_tls = seg; s->lma = seg->addr + (s->off - seg->off); loadable = 1; } return (loadable); } void adjust_addr(struct elfcopy *ecp) { struct section *s, *s0; struct segment *seg; struct sec_action *sac; uint64_t dl, lma, start, end; int found, i; /* * Apply VMA and global LMA changes in the first iteration. */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { /* Only adjust loadable section's address. */ if (!s->loadable || s->seg == NULL) continue; /* Apply global LMA adjustment. */ if (ecp->change_addr != 0) s->lma += ecp->change_addr; if (!s->pseudo) { /* Apply global VMA adjustment. */ if (ecp->change_addr != 0) s->vma += ecp->change_addr; /* Apply section VMA adjustment. */ sac = lookup_sec_act(ecp, s->name, 0); if (sac == NULL) continue; if (sac->setvma) s->vma = sac->vma; if (sac->vma_adjust != 0) s->vma += sac->vma_adjust; } } /* * Apply sections LMA change in the second iteration. */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { /* Only adjust loadable section's LMA. */ if (!s->loadable || s->seg == NULL) continue; /* * Check if there is a LMA change request for this * section. */ sac = lookup_sec_act(ecp, s->name, 0); if (sac == NULL) continue; if (!sac->setlma && sac->lma_adjust == 0) continue; lma = s->lma; if (sac->setlma) lma = sac->lma; if (sac->lma_adjust != 0) lma += sac->lma_adjust; if (lma == s->lma) continue; /* * Check if the LMA change is viable. * * 1. Check if the new LMA is properly aligned accroding to * section alignment. * * 2. Compute the new extent of segment that contains this * section, make sure it doesn't overlap with other * segments. */ #ifdef DEBUG printf("LMA for section %s: %#jx\n", s->name, lma); #endif if (lma % s->align != 0) errx(EXIT_FAILURE, "The load address %#jx for " "section %s is not aligned to %ju", (uintmax_t) lma, s->name, s->align); if (lma < s->lma) { /* Move section to lower address. */ if (lma < s->lma - s->seg->addr) errx(EXIT_FAILURE, "Not enough space to move " "section %s load address to %#jx", s->name, (uintmax_t) lma); start = lma - (s->lma - s->seg->addr); if (s == s->seg->v_sec[s->seg->nsec - 1]) end = start + s->seg->msz; else end = s->seg->addr + s->seg->msz; } else { /* Move section to upper address. */ if (s == s->seg->v_sec[0]) start = lma; else start = s->seg->addr; end = lma + (s->seg->addr + s->seg->msz - s->lma); if (end < start) errx(EXIT_FAILURE, "Not enough space to move " "section %s load address to %#jx", s->name, (uintmax_t) lma); } #ifdef DEBUG printf("new extent for segment containing %s: (%#jx,%#jx)\n", s->name, start, end); #endif STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (seg == s->seg || seg->type != PT_LOAD) continue; if (start > seg->addr + seg->msz) continue; if (end < seg->addr) continue; errx(EXIT_FAILURE, "The extent of segment containing " "section %s overlaps with segment(%#jx,%#jx)", s->name, seg->addr, seg->addr + seg->msz); } /* * Update section LMA and file offset. */ if (lma < s->lma) { /* * To move a section to lower load address, we decrease * the load addresses of the section and all the * sections that are before it, and we increase the * file offsets of all the sections that are after it. */ dl = s->lma - lma; for (i = 0; i < s->seg->nsec; i++) { s0 = s->seg->v_sec[i]; s0->lma -= dl; #ifdef DEBUG printf("section %s LMA set to %#jx\n", s0->name, (uintmax_t) s0->lma); #endif if (s0 == s) break; } for (i = i + 1; i < s->seg->nsec; i++) { s0 = s->seg->v_sec[i]; s0->off += dl; #ifdef DEBUG printf("section %s offset set to %#jx\n", s0->name, (uintmax_t) s0->off); #endif } } else { /* * To move a section to upper load address, we increase * the load addresses of the section and all the * sections that are after it, and we increase the * their file offsets too unless the section in question * is the first in its containing segment. */ dl = lma - s->lma; for (i = 0; i < s->seg->nsec; i++) if (s->seg->v_sec[i] == s) break; if (i >= s->seg->nsec) errx(EXIT_FAILURE, "Internal: section `%s' not" " found in its containing segement", s->name); for (; i < s->seg->nsec; i++) { s0 = s->seg->v_sec[i]; s0->lma += dl; #ifdef DEBUG printf("section %s LMA set to %#jx\n", s0->name, (uintmax_t) s0->lma); #endif if (s != s->seg->v_sec[0]) { s0->off += dl; #ifdef DEBUG printf("section %s offset set to %#jx\n", s0->name, (uintmax_t) s0->off); #endif } } } } /* * Apply load address padding. */ if (ecp->pad_to != 0) { /* * Find the section with highest load address. */ s = NULL; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (seg->type != PT_LOAD) continue; for (i = seg->nsec - 1; i >= 0; i--) if (seg->v_sec[i]->type != SHT_NOBITS) break; if (i < 0) continue; if (s == NULL) s = seg->v_sec[i]; else { s0 = seg->v_sec[i]; if (s0->lma > s->lma) s = s0; } } if (s == NULL) goto issue_warn; /* No need to pad if the pad_to address is lower. */ if (ecp->pad_to <= s->lma + s->sz) goto issue_warn; s->pad_sz = ecp->pad_to - (s->lma + s->sz); #ifdef DEBUG printf("pad section %s load to address %#jx by %#jx\n", s->name, (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz); #endif } issue_warn: /* * Issue a warning if there are VMA/LMA adjust requests for * some nonexistent sections. */ if ((ecp->flags & NO_CHANGE_WARN) == 0) { STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { if (!sac->setvma && !sac->setlma && !sac->vma_adjust && !sac->lma_adjust) continue; found = 0; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->pseudo || s->name == NULL) continue; if (!strcmp(s->name, sac->name)) { found = 1; break; } } if (!found) warnx("cannot find section `%s'", sac->name); } } } static void insert_to_inseg_list(struct segment *seg, struct section *sec) { struct section *s; int i; seg->nsec++; seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec)); if (seg->v_sec == NULL) err(EXIT_FAILURE, "realloc failed"); /* * Sort the section in order of offset. */ for (i = seg->nsec - 1; i > 0; i--) { s = seg->v_sec[i - 1]; if (sec->off >= s->off) { seg->v_sec[i] = sec; break; } else seg->v_sec[i] = s; } if (i == 0) seg->v_sec[0] = sec; } void setup_phdr(struct elfcopy *ecp) { struct segment *seg; GElf_Phdr iphdr; size_t iphnum; int i; if (elf_getphnum(ecp->ein, &iphnum) == 0) errx(EXIT_FAILURE, "elf_getphnum failed: %s", elf_errmsg(-1)); ecp->ophnum = ecp->iphnum = iphnum; if (iphnum == 0) return; /* If --only-keep-debug is specified, discard all program headers. */ if (ecp->strip == STRIP_NONDEBUG) { ecp->ophnum = 0; return; } for (i = 0; (size_t)i < iphnum; i++) { if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) errx(EXIT_FAILURE, "gelf_getphdr failed: %s", elf_errmsg(-1)); if ((seg = calloc(1, sizeof(*seg))) == NULL) err(EXIT_FAILURE, "calloc failed"); seg->addr = iphdr.p_vaddr; seg->off = iphdr.p_offset; seg->fsz = iphdr.p_filesz; seg->msz = iphdr.p_memsz; seg->type = iphdr.p_type; STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list); } } void copy_phdr(struct elfcopy *ecp) { struct segment *seg; struct section *s; GElf_Phdr iphdr, ophdr; int i; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (seg->type == PT_PHDR) { if (!TAILQ_EMPTY(&ecp->v_sec)) { s = TAILQ_FIRST(&ecp->v_sec); if (s->pseudo) seg->addr = s->lma + gelf_fsize(ecp->eout, ELF_T_EHDR, 1, EV_CURRENT); } seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR, ecp->ophnum, EV_CURRENT); continue; } seg->fsz = seg->msz = 0; for (i = 0; i < seg->nsec; i++) { s = seg->v_sec[i]; seg->msz = s->vma + s->sz - seg->addr; if (s->type != SHT_NOBITS) seg->fsz = seg->msz; } } /* * Allocate space for program headers, note that libelf keep * track of the number in internal variable, and a call to * elf_update is needed to update e_phnum of ehdr. */ if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL) errx(EXIT_FAILURE, "gelf_newphdr() failed: %s", elf_errmsg(-1)); /* * This elf_update() call is to update the e_phnum field in * ehdr. It's necessary because later we will call gelf_getphdr(), * which does sanity check by comparing ndx argument with e_phnum. */ if (elf_update(ecp->eout, ELF_C_NULL) < 0) errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); /* * iphnum == ophnum, since we don't remove program headers even if * they no longer contain sections. */ i = 0; STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { if (i >= ecp->iphnum) break; if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) errx(EXIT_FAILURE, "gelf_getphdr failed: %s", elf_errmsg(-1)); if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr) errx(EXIT_FAILURE, "gelf_getphdr failed: %s", elf_errmsg(-1)); ophdr.p_type = iphdr.p_type; ophdr.p_vaddr = seg->addr; ophdr.p_paddr = seg->addr; ophdr.p_flags = iphdr.p_flags; ophdr.p_align = iphdr.p_align; ophdr.p_offset = seg->off; ophdr.p_filesz = seg->fsz; ophdr.p_memsz = seg->msz; if (!gelf_update_phdr(ecp->eout, i, &ophdr)) err(EXIT_FAILURE, "gelf_update_phdr failed :%s", elf_errmsg(-1)); i++; } } Index: head/contrib/elftoolchain/elfcopy/symbols.c =================================================================== --- head/contrib/elftoolchain/elfcopy/symbols.c (revision 280931) +++ head/contrib/elftoolchain/elfcopy/symbols.c (revision 280932) @@ -1,1084 +1,1097 @@ /*- * Copyright (c) 2007-2013 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include "elfcopy.h" -ELFTC_VCSID("$Id: symbols.c 3135 2014-12-24 08:22:43Z kaiwang27 $"); +ELFTC_VCSID("$Id: symbols.c 3174 2015-03-27 17:13:41Z emaste $"); /* Symbol table buffer structure. */ struct symbuf { Elf32_Sym *l32; /* 32bit local symbol */ Elf32_Sym *g32; /* 32bit global symbol */ Elf64_Sym *l64; /* 64bit local symbol */ Elf64_Sym *g64; /* 64bit global symbol */ size_t ngs, nls; /* number of each kind */ size_t gcap, lcap; /* buffer capacities. */ }; struct sthash { LIST_ENTRY(sthash) sh_next; size_t sh_off; }; typedef LIST_HEAD(,sthash) hash_head; #define STHASHSIZE 65536 struct strimpl { char *buf; /* string table */ size_t sz; /* entries */ size_t cap; /* buffer capacity */ hash_head hash[STHASHSIZE]; }; /* String table buffer structure. */ struct strbuf { struct strimpl l; /* local symbols */ struct strimpl g; /* global symbols */ }; static int is_debug_symbol(unsigned char st_info); static int is_global_symbol(unsigned char st_info); static int is_local_symbol(unsigned char st_info); static int is_local_label(const char *name); static int is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s); static int is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, const char *name); static int is_weak_symbol(unsigned char st_info); static int lookup_exact_string(hash_head *hash, const char *buf, const char *s); static int generate_symbols(struct elfcopy *ecp); static void mark_symbols(struct elfcopy *ecp, size_t sc); static int match_wildcard(const char *name, const char *pattern); uint32_t str_hash(const char *s); /* Convenient bit vector operation macros. */ #define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7)) #define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7))) #define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7))) static int is_debug_symbol(unsigned char st_info) { if (GELF_ST_TYPE(st_info) == STT_SECTION || GELF_ST_TYPE(st_info) == STT_FILE) return (1); return (0); } static int is_global_symbol(unsigned char st_info) { if (GELF_ST_BIND(st_info) == STB_GLOBAL) return (1); return (0); } static int is_weak_symbol(unsigned char st_info) { if (GELF_ST_BIND(st_info) == STB_WEAK) return (1); return (0); } static int is_local_symbol(unsigned char st_info) { if (GELF_ST_BIND(st_info) == STB_LOCAL) return (1); return (0); } static int +is_hidden_symbol(unsigned char st_other) +{ + + if (GELF_ST_VISIBILITY(st_other) == STV_HIDDEN || + GELF_ST_VISIBILITY(st_other) == STV_INTERNAL) + return (1); + + return (0); +} + +static int is_local_label(const char *name) { /* Compiler generated local symbols that start with .L */ if (name[0] == '.' && name[1] == 'L') return (1); return (0); } /* * Symbols related to relocation are needed. */ static int is_needed_symbol(struct elfcopy *ecp, int i, GElf_Sym *s) { /* If symbol involves relocation, it is needed. */ if (BIT_ISSET(ecp->v_rel, i)) return (1); /* * For relocatable files (.o files), global and weak symbols * are needed. */ if (ecp->flags & RELOCATABLE) { if (is_global_symbol(s->st_info) || is_weak_symbol(s->st_info)) return (1); } return (0); } static int is_remove_symbol(struct elfcopy *ecp, size_t sc, int i, GElf_Sym *s, const char *name) { GElf_Sym sym0 = { 0, /* st_name */ 0, /* st_value */ 0, /* st_size */ 0, /* st_info */ 0, /* st_other */ SHN_UNDEF, /* st_shndx */ }; if (lookup_symop_list(ecp, name, SYMOP_KEEP) != NULL) return (0); if (lookup_symop_list(ecp, name, SYMOP_STRIP) != NULL) return (1); /* * Keep the first symbol if it is the special reserved symbol. * XXX Should we generate one if it's missing? */ if (i == 0 && !memcmp(s, &sym0, sizeof(GElf_Sym))) return (0); /* Remove the symbol if the section it refers to was removed. */ if (s->st_shndx != SHN_UNDEF && s->st_shndx < SHN_LORESERVE && ecp->secndx[s->st_shndx] == 0) return (1); if (ecp->strip == STRIP_ALL) return (1); if (ecp->v_rel == NULL) mark_symbols(ecp, sc); if (is_needed_symbol(ecp, i, s)) return (0); if (ecp->strip == STRIP_UNNEEDED) return (1); if ((ecp->flags & DISCARD_LOCAL) && is_local_symbol(s->st_info) && !is_debug_symbol(s->st_info)) return (1); if ((ecp->flags & DISCARD_LLABEL) && is_local_symbol(s->st_info) && !is_debug_symbol(s->st_info) && is_local_label(name)) return (1); if (ecp->strip == STRIP_DEBUG && is_debug_symbol(s->st_info)) return (1); return (0); } /* * Mark symbols refered by relocation entries. */ static void mark_symbols(struct elfcopy *ecp, size_t sc) { const char *name; Elf_Data *d; Elf_Scn *s; GElf_Rel r; GElf_Rela ra; GElf_Shdr sh; size_t n, indx; int elferr, i, len; ecp->v_rel = calloc((sc + 7) / 8, 1); if (ecp->v_rel == NULL) err(EXIT_FAILURE, "calloc failed"); if (elf_getshstrndx(ecp->ein, &indx) == 0) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); s = NULL; while ((s = elf_nextscn(ecp->ein, s)) != NULL) { if (gelf_getshdr(s, &sh) != &sh) errx(EXIT_FAILURE, "elf_getshdr failed: %s", elf_errmsg(-1)); if (sh.sh_type != SHT_REL && sh.sh_type != SHT_RELA) continue; /* * Skip if this reloc section won't appear in the * output object. */ if ((name = elf_strptr(ecp->ein, indx, sh.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); if (is_remove_section(ecp, name) || is_remove_reloc_sec(ecp, sh.sh_info)) continue; /* Skip if it's not for .symtab */ if (sh.sh_link != elf_ndxscn(ecp->symtab->is)) continue; d = NULL; n = 0; while (n < sh.sh_size && (d = elf_getdata(s, d)) != NULL) { len = d->d_size / sh.sh_entsize; for (i = 0; i < len; i++) { if (sh.sh_type == SHT_REL) { if (gelf_getrel(d, i, &r) != &r) errx(EXIT_FAILURE, "elf_getrel failed: %s", elf_errmsg(-1)); n = GELF_R_SYM(r.r_info); } else { if (gelf_getrela(d, i, &ra) != &ra) errx(EXIT_FAILURE, "elf_getrela failed: %s", elf_errmsg(-1)); n = GELF_R_SYM(ra.r_info); } if (n > 0 && n < sc) BIT_SET(ecp->v_rel, n); else if (n != 0) warnx("invalid symbox index"); } } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata failed: %s", elf_errmsg(elferr)); } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); } static int generate_symbols(struct elfcopy *ecp) { struct section *s; struct symop *sp; struct symbuf *sy_buf; struct strbuf *st_buf; const char *name; char *newname; unsigned char *gsym; GElf_Shdr ish; GElf_Sym sym; Elf_Data* id; Elf_Scn *is; size_t ishstrndx, namelen, ndx, sc, symndx; int ec, elferr, i; if (elf_getshstrndx(ecp->ein, &ishstrndx) == 0) errx(EXIT_FAILURE, "elf_getshstrndx failed: %s", elf_errmsg(-1)); if ((ec = gelf_getclass(ecp->eout)) == ELFCLASSNONE) errx(EXIT_FAILURE, "gelf_getclass failed: %s", elf_errmsg(-1)); /* Create buffers for .symtab and .strtab. */ if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) err(EXIT_FAILURE, "calloc failed"); if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) err(EXIT_FAILURE, "calloc failed"); sy_buf->gcap = sy_buf->lcap = 64; st_buf->g.cap = 256; st_buf->l.cap = 64; st_buf->l.sz = 1; /* '\0' at start. */ st_buf->g.sz = 0; ecp->symtab->sz = 0; ecp->strtab->sz = 0; ecp->symtab->buf = sy_buf; ecp->strtab->buf = st_buf; /* * Create bit vector v_secsym, which is used to mark sections * that already have corresponding STT_SECTION symbols. */ ecp->v_secsym = calloc((ecp->nos + 7) / 8, 1); if (ecp->v_secsym == NULL) err(EXIT_FAILURE, "calloc failed"); /* Locate .strtab of input object. */ symndx = 0; name = NULL; is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (gelf_getshdr(is, &ish) != &ish) errx(EXIT_FAILURE, "elf_getshdr failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); if (strcmp(name, ".strtab") == 0) { symndx = elf_ndxscn(is); break; } } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); /* Symbol table should exist if this function is called. */ if (symndx == 0) { warnx("can't find .strtab section"); return (0); } /* Locate .symtab of input object. */ is = NULL; while ((is = elf_nextscn(ecp->ein, is)) != NULL) { if (gelf_getshdr(is, &ish) != &ish) errx(EXIT_FAILURE, "elf_getshdr failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, ishstrndx, ish.sh_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); if (strcmp(name, ".symtab") == 0) break; } elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_nextscn failed: %s", elf_errmsg(elferr)); if (is == NULL) errx(EXIT_FAILURE, "can't find .strtab section"); /* * Create bit vector gsym to mark global symbols, and symndx * to keep track of symbol index changes from input object to * output object, it is used by update_reloc() later to update * relocation information. */ gsym = NULL; sc = ish.sh_size / ish.sh_entsize; if (sc > 0) { ecp->symndx = calloc(sc, sizeof(*ecp->symndx)); if (ecp->symndx == NULL) err(EXIT_FAILURE, "calloc failed"); gsym = calloc((sc + 7) / 8, sizeof(*gsym)); if (gsym == NULL) err(EXIT_FAILURE, "calloc failed"); if ((id = elf_getdata(is, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) errx(EXIT_FAILURE, "elf_getdata failed: %s", elf_errmsg(elferr)); return (0); } } else return (0); /* Copy/Filter each symbol. */ for (i = 0; (size_t)i < sc; i++) { if (gelf_getsym(id, i, &sym) != &sym) errx(EXIT_FAILURE, "gelf_getsym failed: %s", elf_errmsg(-1)); if ((name = elf_strptr(ecp->ein, symndx, sym.st_name)) == NULL) errx(EXIT_FAILURE, "elf_strptr failed: %s", elf_errmsg(-1)); /* Symbol filtering. */ if (is_remove_symbol(ecp, sc, i, &sym, name) != 0) continue; /* Check if we need to change the binding of this symbol. */ if (is_global_symbol(sym.st_info) || is_weak_symbol(sym.st_info)) { /* * XXX Binutils objcopy does not weaken certain * symbols. */ if (ecp->flags & WEAKEN_ALL || lookup_symop_list(ecp, name, SYMOP_WEAKEN) != NULL) sym.st_info = GELF_ST_INFO(STB_WEAK, GELF_ST_TYPE(sym.st_info)); /* Do not localize undefined symbols. */ if (sym.st_shndx != SHN_UNDEF && lookup_symop_list(ecp, name, SYMOP_LOCALIZE) != NULL) sym.st_info = GELF_ST_INFO(STB_LOCAL, GELF_ST_TYPE(sym.st_info)); if (ecp->flags & KEEP_GLOBAL && sym.st_shndx != SHN_UNDEF && lookup_symop_list(ecp, name, SYMOP_KEEPG) == NULL) sym.st_info = GELF_ST_INFO(STB_LOCAL, GELF_ST_TYPE(sym.st_info)); + if (ecp->flags & LOCALIZE_HIDDEN && + sym.st_shndx != SHN_UNDEF && + is_hidden_symbol(sym.st_other)) + sym.st_info = GELF_ST_INFO(STB_LOCAL, + GELF_ST_TYPE(sym.st_info)); } else { /* STB_LOCAL binding. */ if (lookup_symop_list(ecp, name, SYMOP_GLOBALIZE) != NULL) sym.st_info = GELF_ST_INFO(STB_GLOBAL, GELF_ST_TYPE(sym.st_info)); /* XXX We should globalize weak symbol? */ } /* Check if we need to rename this symbol. */ if ((sp = lookup_symop_list(ecp, name, SYMOP_REDEF)) != NULL) name = sp->newname; /* Check if we need to prefix the symbols. */ newname = NULL; if (ecp->prefix_sym != NULL && name != NULL && *name != '\0') { namelen = strlen(name) + strlen(ecp->prefix_sym) + 1; if ((newname = malloc(namelen)) == NULL) err(EXIT_FAILURE, "malloc failed"); snprintf(newname, namelen, "%s%s", ecp->prefix_sym, name); name = newname; } /* Copy symbol, mark global/weak symbol and add to index map. */ if (is_global_symbol(sym.st_info) || is_weak_symbol(sym.st_info)) { BIT_SET(gsym, i); ecp->symndx[i] = sy_buf->ngs; } else ecp->symndx[i] = sy_buf->nls; add_to_symtab(ecp, name, sym.st_value, sym.st_size, sym.st_shndx, sym.st_info, sym.st_other, 0); if (newname != NULL) free(newname); /* * If the symbol is a STT_SECTION symbol, mark the section * it points to. */ if (GELF_ST_TYPE(sym.st_info) == STT_SECTION) BIT_SET(ecp->v_secsym, ecp->secndx[sym.st_shndx]); } /* * Give up if there is no real symbols inside the table. * XXX The logic here needs to be improved. We need to * check if that only local symbol is the reserved symbol. */ if (sy_buf->nls <= 1 && sy_buf->ngs == 0) return (0); /* * Create STT_SECTION symbols for sections that do not already * got one. However, we do not create STT_SECTION symbol for * .symtab, .strtab, .shstrtab and reloc sec of relocatables. */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->pseudo) continue; if (strcmp(s->name, ".symtab") == 0 || strcmp(s->name, ".strtab") == 0 || strcmp(s->name, ".shstrtab") == 0) continue; if ((ecp->flags & RELOCATABLE) != 0 && ((s->type == SHT_REL) || (s->type == SHT_RELA))) continue; if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) errx(EXIT_FAILURE, "elf_ndxscn failed: %s", elf_errmsg(-1)); if (!BIT_ISSET(ecp->v_secsym, ndx)) { sym.st_name = 0; sym.st_value = s->vma; sym.st_size = 0; sym.st_info = GELF_ST_INFO(STB_LOCAL, STT_SECTION); /* * Don't let add_to_symtab() touch sym.st_shndx. * In this case, we know the index already. */ add_to_symtab(ecp, NULL, sym.st_value, sym.st_size, ndx, sym.st_info, sym.st_other, 1); } } /* * Update st_name and index map for global/weak symbols. Note that * global/weak symbols are put after local symbols. */ if (gsym != NULL) { for(i = 0; (size_t) i < sc; i++) { if (!BIT_ISSET(gsym, i)) continue; /* Update st_name. */ if (ec == ELFCLASS32) sy_buf->g32[ecp->symndx[i]].st_name += st_buf->l.sz; else sy_buf->g64[ecp->symndx[i]].st_name += st_buf->l.sz; /* Update index map. */ ecp->symndx[i] += sy_buf->nls; } free(gsym); } return (1); } void create_symtab(struct elfcopy *ecp) { struct section *s, *sy, *st; size_t maxndx, ndx; sy = ecp->symtab; st = ecp->strtab; /* * Set section index map for .symtab and .strtab. We need to set * these map because otherwise symbols which refer to .symtab and * .strtab will be removed by symbol filtering unconditionally. * And we have to figure out scn index this way (instead of calling * elf_ndxscn) because we can not create Elf_Scn before we're certain * that .symtab and .strtab will exist in the output object. */ maxndx = 0; TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->os == NULL) continue; if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) errx(EXIT_FAILURE, "elf_ndxscn failed: %s", elf_errmsg(-1)); if (ndx > maxndx) maxndx = ndx; } ecp->secndx[elf_ndxscn(sy->is)] = maxndx + 1; ecp->secndx[elf_ndxscn(st->is)] = maxndx + 2; /* * Generate symbols for output object if SYMTAB_INTACT is not set. * If there is no symbol in the input object or all the symbols are * stripped, then free all the resouces allotted for symbol table, * and clear SYMTAB_EXIST flag. */ if (((ecp->flags & SYMTAB_INTACT) == 0) && !generate_symbols(ecp)) { TAILQ_REMOVE(&ecp->v_sec, ecp->symtab, sec_list); TAILQ_REMOVE(&ecp->v_sec, ecp->strtab, sec_list); free(ecp->symtab); free(ecp->strtab); ecp->symtab = NULL; ecp->strtab = NULL; ecp->flags &= ~SYMTAB_EXIST; return; } /* Create output Elf_Scn for .symtab and .strtab. */ if ((sy->os = elf_newscn(ecp->eout)) == NULL || (st->os = elf_newscn(ecp->eout)) == NULL) errx(EXIT_FAILURE, "elf_newscn failed: %s", elf_errmsg(-1)); /* Update secndx anyway. */ ecp->secndx[elf_ndxscn(sy->is)] = elf_ndxscn(sy->os); ecp->secndx[elf_ndxscn(st->is)] = elf_ndxscn(st->os); /* * Copy .symtab and .strtab section headers from input to output * object to start with, these will be overridden later if need. */ copy_shdr(ecp, sy, ".symtab", 1, 0); copy_shdr(ecp, st, ".strtab", 1, 0); /* Copy verbatim if symbol table is intact. */ if (ecp->flags & SYMTAB_INTACT) { copy_data(sy); copy_data(st); return; } create_symtab_data(ecp); } void free_symtab(struct elfcopy *ecp) { struct symbuf *sy_buf; struct strbuf *st_buf; struct sthash *sh, *shtmp; int i; if (ecp->symtab != NULL && ecp->symtab->buf != NULL) { sy_buf = ecp->symtab->buf; if (sy_buf->l32 != NULL) free(sy_buf->l32); if (sy_buf->g32 != NULL) free(sy_buf->g32); if (sy_buf->l64 != NULL) free(sy_buf->l64); if (sy_buf->g64 != NULL) free(sy_buf->g64); } if (ecp->strtab != NULL && ecp->strtab->buf != NULL) { st_buf = ecp->strtab->buf; if (st_buf->l.buf != NULL) free(st_buf->l.buf); if (st_buf->g.buf != NULL) free(st_buf->g.buf); for (i = 0; i < STHASHSIZE; i++) { LIST_FOREACH_SAFE(sh, &st_buf->l.hash[i], sh_next, shtmp) { LIST_REMOVE(sh, sh_next); free(sh); } LIST_FOREACH_SAFE(sh, &st_buf->g.hash[i], sh_next, shtmp) { LIST_REMOVE(sh, sh_next); free(sh); } } } } void create_external_symtab(struct elfcopy *ecp) { struct section *s; struct symbuf *sy_buf; struct strbuf *st_buf; GElf_Shdr sh; size_t ndx; if (ecp->oec == ELFCLASS32) ecp->symtab = create_external_section(ecp, ".symtab", NULL, NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 4, 0, 0); else ecp->symtab = create_external_section(ecp, ".symtab", NULL, NULL, 0, 0, SHT_SYMTAB, ELF_T_SYM, 0, 8, 0, 0); ecp->strtab = create_external_section(ecp, ".strtab", NULL, NULL, 0, 0, SHT_STRTAB, ELF_T_BYTE, 0, 1, 0, 0); /* Let sh_link field of .symtab section point to .strtab section. */ if (gelf_getshdr(ecp->symtab->os, &sh) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); sh.sh_link = elf_ndxscn(ecp->strtab->os); if (!gelf_update_shdr(ecp->symtab->os, &sh)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); /* Create buffers for .symtab and .strtab. */ if ((sy_buf = calloc(1, sizeof(*sy_buf))) == NULL) err(EXIT_FAILURE, "calloc failed"); if ((st_buf = calloc(1, sizeof(*st_buf))) == NULL) err(EXIT_FAILURE, "calloc failed"); sy_buf->gcap = sy_buf->lcap = 64; st_buf->g.cap = 256; st_buf->l.cap = 64; st_buf->l.sz = 1; /* '\0' at start. */ st_buf->g.sz = 0; ecp->symtab->sz = 0; ecp->strtab->sz = 0; ecp->symtab->buf = sy_buf; ecp->strtab->buf = st_buf; /* Always create the special symbol at the symtab beginning. */ add_to_symtab(ecp, NULL, 0, 0, SHN_UNDEF, ELF32_ST_INFO(STB_LOCAL, STT_NOTYPE), 0, 1); /* Create STT_SECTION symbols. */ TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { if (s->pseudo) continue; if (strcmp(s->name, ".symtab") == 0 || strcmp(s->name, ".strtab") == 0 || strcmp(s->name, ".shstrtab") == 0) continue; (void) elf_errno(); if ((ndx = elf_ndxscn(s->os)) == SHN_UNDEF) { warnx("elf_ndxscn failed: %s", elf_errmsg(-1)); continue; } add_to_symtab(ecp, NULL, 0, 0, ndx, GELF_ST_INFO(STB_LOCAL, STT_SECTION), 0, 1); } } void add_to_symtab(struct elfcopy *ecp, const char *name, uint64_t st_value, uint64_t st_size, uint16_t st_shndx, unsigned char st_info, unsigned char st_other, int ndx_known) { struct symbuf *sy_buf; struct strbuf *st_buf; struct sthash *sh; uint32_t hash; int pos; /* * Convenient macro for copying global/local 32/64 bit symbols * from input object to the buffer created for output object. * It handles buffer growing, st_name calculating and st_shndx * updating for symbols with non-special section index. */ #define _ADDSYM(B, SZ) do { \ if (sy_buf->B##SZ == NULL) { \ sy_buf->B##SZ = malloc(sy_buf->B##cap * \ sizeof(Elf##SZ##_Sym)); \ if (sy_buf->B##SZ == NULL) \ err(EXIT_FAILURE, "malloc failed"); \ } else if (sy_buf->n##B##s >= sy_buf->B##cap) { \ sy_buf->B##cap *= 2; \ sy_buf->B##SZ = realloc(sy_buf->B##SZ, sy_buf->B##cap * \ sizeof(Elf##SZ##_Sym)); \ if (sy_buf->B##SZ == NULL) \ err(EXIT_FAILURE, "realloc failed"); \ } \ sy_buf->B##SZ[sy_buf->n##B##s].st_info = st_info; \ sy_buf->B##SZ[sy_buf->n##B##s].st_other = st_other; \ sy_buf->B##SZ[sy_buf->n##B##s].st_value = st_value; \ sy_buf->B##SZ[sy_buf->n##B##s].st_size = st_size; \ if (ndx_known) \ sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ else if (st_shndx == SHN_UNDEF || st_shndx >= SHN_LORESERVE) \ sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = st_shndx; \ else \ sy_buf->B##SZ[sy_buf->n##B##s].st_shndx = \ ecp->secndx[st_shndx]; \ if (st_buf->B.buf == NULL) { \ st_buf->B.buf = calloc(st_buf->B.cap, \ sizeof(*st_buf->B.buf)); \ if (st_buf->B.buf == NULL) \ err(EXIT_FAILURE, "malloc failed"); \ } \ if (name != NULL && *name != '\0') { \ pos = lookup_exact_string(st_buf->B.hash, st_buf->B.buf,\ name); \ if (pos != -1) \ sy_buf->B##SZ[sy_buf->n##B##s].st_name = pos; \ else { \ sy_buf->B##SZ[sy_buf->n##B##s].st_name = \ st_buf->B.sz; \ while (st_buf->B.sz + strlen(name) >= \ st_buf->B.cap - 1) { \ st_buf->B.cap *= 2; \ st_buf->B.buf = realloc(st_buf->B.buf, \ st_buf->B.cap); \ if (st_buf->B.buf == NULL) \ err(EXIT_FAILURE, \ "realloc failed"); \ } \ if ((sh = malloc(sizeof(*sh))) == NULL) \ err(EXIT_FAILURE, "malloc failed"); \ sh->sh_off = st_buf->B.sz; \ hash = str_hash(name); \ LIST_INSERT_HEAD(&st_buf->B.hash[hash], sh, \ sh_next); \ strncpy(&st_buf->B.buf[st_buf->B.sz], name, \ strlen(name)); \ st_buf->B.buf[st_buf->B.sz + strlen(name)] = '\0'; \ st_buf->B.sz += strlen(name) + 1; \ } \ } else \ sy_buf->B##SZ[sy_buf->n##B##s].st_name = 0; \ sy_buf->n##B##s++; \ } while (0) sy_buf = ecp->symtab->buf; st_buf = ecp->strtab->buf; if (ecp->oec == ELFCLASS32) { if (is_local_symbol(st_info)) _ADDSYM(l, 32); else _ADDSYM(g, 32); } else { if (is_local_symbol(st_info)) _ADDSYM(l, 64); else _ADDSYM(g, 64); } /* Update section size. */ ecp->symtab->sz = (sy_buf->nls + sy_buf->ngs) * (ecp->oec == ELFCLASS32 ? sizeof(Elf32_Sym) : sizeof(Elf64_Sym)); ecp->strtab->sz = st_buf->l.sz + st_buf->g.sz; #undef _ADDSYM } void finalize_external_symtab(struct elfcopy *ecp) { struct symbuf *sy_buf; struct strbuf *st_buf; int i; /* * Update st_name for global/weak symbols. (global/weak symbols * are put after local symbols) */ sy_buf = ecp->symtab->buf; st_buf = ecp->strtab->buf; for (i = 0; (size_t) i < sy_buf->ngs; i++) { if (ecp->oec == ELFCLASS32) sy_buf->g32[i].st_name += st_buf->l.sz; else sy_buf->g64[i].st_name += st_buf->l.sz; } } void create_symtab_data(struct elfcopy *ecp) { struct section *sy, *st; struct symbuf *sy_buf; struct strbuf *st_buf; Elf_Data *gsydata, *lsydata, *gstdata, *lstdata; GElf_Shdr shy, sht; sy = ecp->symtab; st = ecp->strtab; if (gelf_getshdr(sy->os, ­) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); if (gelf_getshdr(st->os, &sht) == NULL) errx(EXIT_FAILURE, "gelf_getshdr() failed: %s", elf_errmsg(-1)); /* * Create two Elf_Data for .symtab section of output object, one * for local symbols and another for global symbols. Note that * local symbols appear first in the .symtab. */ sy_buf = sy->buf; if (sy_buf->nls > 0) { if ((lsydata = elf_newdata(sy->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s.", elf_errmsg(-1)); if (ecp->oec == ELFCLASS32) { lsydata->d_align = 4; lsydata->d_off = 0; lsydata->d_buf = sy_buf->l32; lsydata->d_size = sy_buf->nls * sizeof(Elf32_Sym); lsydata->d_type = ELF_T_SYM; lsydata->d_version = EV_CURRENT; } else { lsydata->d_align = 8; lsydata->d_off = 0; lsydata->d_buf = sy_buf->l64; lsydata->d_size = sy_buf->nls * sizeof(Elf64_Sym); lsydata->d_type = ELF_T_SYM; lsydata->d_version = EV_CURRENT; } } if (sy_buf->ngs > 0) { if ((gsydata = elf_newdata(sy->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s.", elf_errmsg(-1)); if (ecp->oec == ELFCLASS32) { gsydata->d_align = 4; gsydata->d_off = sy_buf->nls * sizeof(Elf32_Sym); gsydata->d_buf = sy_buf->g32; gsydata->d_size = sy_buf->ngs * sizeof(Elf32_Sym); gsydata->d_type = ELF_T_SYM; gsydata->d_version = EV_CURRENT; } else { gsydata->d_align = 8; gsydata->d_off = sy_buf->nls * sizeof(Elf64_Sym); gsydata->d_buf = sy_buf->g64; gsydata->d_size = sy_buf->ngs * sizeof(Elf64_Sym); gsydata->d_type = ELF_T_SYM; gsydata->d_version = EV_CURRENT; } } /* * Create two Elf_Data for .strtab, one for local symbol name * and another for globals. Same as .symtab, local symbol names * appear first. */ st_buf = st->buf; if ((lstdata = elf_newdata(st->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s.", elf_errmsg(-1)); lstdata->d_align = 1; lstdata->d_off = 0; lstdata->d_buf = st_buf->l.buf; lstdata->d_size = st_buf->l.sz; lstdata->d_type = ELF_T_BYTE; lstdata->d_version = EV_CURRENT; if (st_buf->g.sz > 0) { if ((gstdata = elf_newdata(st->os)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s.", elf_errmsg(-1)); gstdata->d_align = 1; gstdata->d_off = lstdata->d_size; gstdata->d_buf = st_buf->g.buf; gstdata->d_size = st_buf->g.sz; gstdata->d_type = ELF_T_BYTE; gstdata->d_version = EV_CURRENT; } shy.sh_addr = 0; shy.sh_addralign = (ecp->oec == ELFCLASS32 ? 4 : 8); shy.sh_size = sy->sz; shy.sh_type = SHT_SYMTAB; shy.sh_flags = 0; shy.sh_entsize = gelf_fsize(ecp->eout, ELF_T_SYM, 1, EV_CURRENT); /* * According to SYSV abi, here sh_info is one greater than * the symbol table index of the last local symbol(binding * STB_LOCAL). */ shy.sh_info = sy_buf->nls; sht.sh_addr = 0; sht.sh_addralign = 1; sht.sh_size = st->sz; sht.sh_type = SHT_STRTAB; sht.sh_flags = 0; sht.sh_entsize = 0; sht.sh_info = 0; sht.sh_link = 0; if (!gelf_update_shdr(sy->os, ­)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); if (!gelf_update_shdr(st->os, &sht)) errx(EXIT_FAILURE, "gelf_update_shdr() failed: %s", elf_errmsg(-1)); } void add_to_symop_list(struct elfcopy *ecp, const char *name, const char *newname, unsigned int op) { struct symop *s; if ((s = lookup_symop_list(ecp, name, ~0U)) == NULL) { if ((s = calloc(1, sizeof(*s))) == NULL) errx(EXIT_FAILURE, "not enough memory"); s->name = name; if (op == SYMOP_REDEF) s->newname = newname; } s->op |= op; STAILQ_INSERT_TAIL(&ecp->v_symop, s, symop_list); } static int match_wildcard(const char *name, const char *pattern) { int reverse, match; reverse = 0; if (*pattern == '!') { reverse = 1; pattern++; } match = 0; - if (!fnmatch(pattern, name, 0)) { + if (!fnmatch(pattern, name, 0)) match = 1; - printf("string '%s' match to pattern '%s'\n", name, pattern); - } return (reverse ? !match : match); } struct symop * lookup_symop_list(struct elfcopy *ecp, const char *name, unsigned int op) { struct symop *s; STAILQ_FOREACH(s, &ecp->v_symop, symop_list) { if (name == NULL || !strcmp(name, s->name) || ((ecp->flags & WILDCARD) && match_wildcard(name, s->name))) if ((s->op & op) != 0) return (s); } return (NULL); } static int lookup_exact_string(hash_head *buckets, const char *buf, const char *s) { struct sthash *sh; uint32_t hash; hash = str_hash(s); LIST_FOREACH(sh, &buckets[hash], sh_next) if (strcmp(buf + sh->sh_off, s) == 0) return sh->sh_off; return (-1); } uint32_t str_hash(const char *s) { uint32_t hash; for (hash = 2166136261; *s; s++) hash = (hash ^ *s) * 16777619; return (hash & (STHASHSIZE - 1)); } Index: head/contrib/elftoolchain/libdwarf/_libdwarf.h =================================================================== --- head/contrib/elftoolchain/libdwarf/_libdwarf.h (revision 280931) +++ head/contrib/elftoolchain/libdwarf/_libdwarf.h (revision 280932) @@ -1,665 +1,666 @@ /*- * Copyright (c) 2007 John Birrell (jb@freebsd.org) * Copyright (c) 2009-2014 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libdwarf.h 3161 2015-02-15 21:43:36Z emaste $ + * $Id: _libdwarf.h 3164 2015-02-19 01:20:12Z kaiwang27 $ */ #ifndef __LIBDWARF_H_ #define __LIBDWARF_H_ #include #include #include #include #include #include #include #include #include "dwarf.h" #include "libdwarf.h" #include "uthash.h" #include "_elftc.h" #define DWARF_DIE_HASH_SIZE 8191 struct _libdwarf_globals { Dwarf_Handler errhand; Dwarf_Ptr errarg; int applyreloc; }; extern struct _libdwarf_globals _libdwarf; #define _DWARF_SET_ERROR(_d, _e, _err, _elf_err) \ _dwarf_set_error(_d, _e, _err, _elf_err, __func__, __LINE__) #define DWARF_SET_ERROR(_d, _e, _err) \ _DWARF_SET_ERROR(_d, _e, _err, 0) #define DWARF_SET_ELF_ERROR(_d, _e) \ _DWARF_SET_ERROR(_d, _e, DW_DLE_ELF, elf_errno()) /* * Convenient macros for producer bytes stream generation. */ #define WRITE_VALUE(value, bytes) \ dbg->write_alloc(&ds->ds_data, &ds->ds_cap, &ds->ds_size, \ (value), (bytes), error) #define WRITE_ULEB128(value) \ _dwarf_write_uleb128_alloc(&ds->ds_data, &ds->ds_cap, \ &ds->ds_size, (value), error) #define WRITE_SLEB128(value) \ _dwarf_write_sleb128_alloc(&ds->ds_data, &ds->ds_cap, \ &ds->ds_size, (value), error) #define WRITE_STRING(string) \ _dwarf_write_string_alloc(&ds->ds_data, &ds->ds_cap, \ &ds->ds_size, (string), error) #define WRITE_BLOCK(blk, size) \ _dwarf_write_block_alloc(&ds->ds_data, &ds->ds_cap, \ &ds->ds_size, (blk), (size), error) #define WRITE_PADDING(byte, cnt) \ _dwarf_write_padding_alloc(&ds->ds_data, &ds->ds_cap, \ &ds->ds_size, (byte), (cnt), error) #define RCHECK(expr) \ do { \ ret = expr; \ if (ret != DW_DLE_NONE) \ goto gen_fail; \ } while(0) typedef struct _Dwarf_CU *Dwarf_CU; struct _Dwarf_AttrDef { uint64_t ad_attrib; /* DW_AT_XXX */ uint64_t ad_form; /* DW_FORM_XXX */ uint64_t ad_offset; /* Offset in abbrev section. */ STAILQ_ENTRY(_Dwarf_AttrDef) ad_next; /* Next attribute define. */ }; struct _Dwarf_Attribute { Dwarf_Die at_die; /* Ptr to containing DIE. */ Dwarf_Die at_refdie; /* Ptr to reference DIE. */ uint64_t at_offset; /* Offset in info section. */ uint64_t at_attrib; /* DW_AT_XXX */ uint64_t at_form; /* DW_FORM_XXX */ int at_indirect; /* Has indirect form. */ union { uint64_t u64; /* Unsigned value. */ int64_t s64; /* Signed value. */ char *s; /* String. */ uint8_t *u8p; /* Block data. */ } u[2]; /* Value. */ Dwarf_Block at_block; /* Block. */ Dwarf_Locdesc *at_ld; /* at value is locdesc. */ Dwarf_P_Expr at_expr; /* at value is expr. */ uint64_t at_relsym; /* Relocation symbol index. */ const char *at_relsec; /* Rel. to dwarf section. */ STAILQ_ENTRY(_Dwarf_Attribute) at_next; /* Next attribute. */ }; struct _Dwarf_Abbrev { uint64_t ab_entry; /* Abbrev entry. */ uint64_t ab_tag; /* Tag: DW_TAG_ */ uint8_t ab_children; /* DW_CHILDREN_no or DW_CHILDREN_yes */ uint64_t ab_offset; /* Offset in abbrev section. */ uint64_t ab_length; /* Length of this abbrev entry. */ uint64_t ab_atnum; /* Number of attribute defines. */ UT_hash_handle ab_hh; /* Uthash handle. */ STAILQ_HEAD(, _Dwarf_AttrDef) ab_attrdef; /* List of attribute defs. */ }; struct _Dwarf_Die { Dwarf_Die die_parent; /* Parent DIE. */ Dwarf_Die die_child; /* First child DIE. */ Dwarf_Die die_left; /* Left sibling DIE. */ Dwarf_Die die_right; /* Right sibling DIE. */ uint64_t die_offset; /* DIE offset in section. */ uint64_t die_next_off; /* Next DIE offset in section. */ uint64_t die_abnum; /* Abbrev number. */ Dwarf_Abbrev die_ab; /* Abbrev pointer. */ Dwarf_Tag die_tag; /* DW_TAG_ */ Dwarf_Debug die_dbg; /* Dwarf_Debug pointer. */ Dwarf_CU die_cu; /* Compilation unit pointer. */ char *die_name; /* Ptr to the name string. */ Dwarf_Attribute *die_attrarray; /* Array of attributes. */ STAILQ_HEAD(, _Dwarf_Attribute) die_attr; /* List of attributes. */ STAILQ_ENTRY(_Dwarf_Die) die_pro_next; /* Next die in pro-die list. */ }; struct _Dwarf_P_Expr_Entry { Dwarf_Loc ee_loc; /* Location expression. */ Dwarf_Unsigned ee_sym; /* Optional related reloc sym index. */ STAILQ_ENTRY(_Dwarf_P_Expr_Entry) ee_next; /* Next entry in list. */ }; struct _Dwarf_P_Expr { Dwarf_Debug pe_dbg; /* Dwarf_Debug pointer. */ uint8_t *pe_block; /* Expression block data. */ int pe_invalid; /* Block data is up-to-date or not. */ Dwarf_Unsigned pe_length; /* Length of the block. */ STAILQ_HEAD(, _Dwarf_P_Expr_Entry) pe_eelist; /* List of entries. */ STAILQ_ENTRY(_Dwarf_P_Expr) pe_next; /* Next expr in list. */ }; struct _Dwarf_Line { Dwarf_LineInfo ln_li; /* Ptr to line info. */ Dwarf_Addr ln_addr; /* Line address. */ Dwarf_Unsigned ln_symndx; /* Symbol index for relocation. */ Dwarf_Unsigned ln_fileno; /* File number. */ Dwarf_Unsigned ln_lineno; /* Line number. */ Dwarf_Signed ln_column; /* Column number. */ Dwarf_Bool ln_bblock; /* Basic block flag. */ Dwarf_Bool ln_stmt; /* Begin statement flag. */ Dwarf_Bool ln_endseq; /* End sequence flag. */ STAILQ_ENTRY(_Dwarf_Line) ln_next; /* Next line in list. */ }; struct _Dwarf_LineFile { char *lf_fname; /* Filename. */ char *lf_fullpath; /* Full pathname of the file. */ Dwarf_Unsigned lf_dirndx; /* Dir index. */ Dwarf_Unsigned lf_mtime; /* Modification time. */ Dwarf_Unsigned lf_size; /* File size. */ STAILQ_ENTRY(_Dwarf_LineFile) lf_next; /* Next file in list. */ }; struct _Dwarf_LineInfo { Dwarf_Unsigned li_length; /* Length of line info data. */ Dwarf_Half li_version; /* Version of line info. */ Dwarf_Unsigned li_hdrlen; /* Length of line info header. */ Dwarf_Small li_minlen; /* Minimum instrutction length. */ + Dwarf_Small li_maxop; /* Maximum operations per inst. */ Dwarf_Small li_defstmt; /* Default value of is_stmt. */ int8_t li_lbase; /* Line base for special opcode. */ Dwarf_Small li_lrange; /* Line range for special opcode. */ Dwarf_Small li_opbase; /* Fisrt std opcode number. */ Dwarf_Small *li_oplen; /* Array of std opcode len. */ char **li_incdirs; /* Array of include dirs. */ Dwarf_Unsigned li_inclen; /* Length of inc dir array. */ char **li_lfnarray; /* Array of file names. */ Dwarf_Unsigned li_lflen; /* Length of filename array. */ STAILQ_HEAD(, _Dwarf_LineFile) li_lflist; /* List of files. */ Dwarf_Line *li_lnarray; /* Array of lines. */ Dwarf_Unsigned li_lnlen; /* Length of the line array. */ STAILQ_HEAD(, _Dwarf_Line) li_lnlist; /* List of lines. */ }; struct _Dwarf_NamePair { Dwarf_NameTbl np_nt; /* Ptr to containing name table. */ Dwarf_Die np_die; /* Ptr to Ref. Die. */ Dwarf_Unsigned np_offset; /* Offset in CU. */ char *np_name; /* Object/Type name. */ STAILQ_ENTRY(_Dwarf_NamePair) np_next; /* Next pair in the list. */ }; struct _Dwarf_NameTbl { Dwarf_Unsigned nt_length; /* Name lookup table length. */ Dwarf_Half nt_version; /* Name lookup table version. */ Dwarf_CU nt_cu; /* Ptr to Ref. CU. */ Dwarf_Off nt_cu_offset; /* Ref. CU offset in .debug_info */ Dwarf_Unsigned nt_cu_length; /* Ref. CU length. */ STAILQ_HEAD(, _Dwarf_NamePair) nt_nplist; /* List of offset+name pairs. */ STAILQ_ENTRY(_Dwarf_NameTbl) nt_next; /* Next name table in the list. */ }; struct _Dwarf_NameSec { STAILQ_HEAD(, _Dwarf_NameTbl) ns_ntlist; /* List of name tables. */ Dwarf_NamePair *ns_array; /* Array of pairs of all tables. */ Dwarf_Unsigned ns_len; /* Length of the pair array. */ }; struct _Dwarf_Fde { Dwarf_Debug fde_dbg; /* Ptr to containing dbg. */ Dwarf_Cie fde_cie; /* Ptr to associated CIE. */ Dwarf_FrameSec fde_fs; /* Ptr to containing .debug_frame. */ Dwarf_Ptr fde_addr; /* Ptr to start of the FDE. */ Dwarf_Unsigned fde_offset; /* Offset of the FDE. */ Dwarf_Unsigned fde_length; /* Length of the FDE. */ Dwarf_Unsigned fde_cieoff; /* Offset of associated CIE. */ Dwarf_Unsigned fde_initloc; /* Initial location. */ Dwarf_Unsigned fde_adrange; /* Address range. */ Dwarf_Unsigned fde_auglen; /* Augmentation length. */ uint8_t *fde_augdata; /* Augmentation data. */ uint8_t *fde_inst; /* Instructions. */ Dwarf_Unsigned fde_instlen; /* Length of instructions. */ Dwarf_Unsigned fde_instcap; /* Capacity of inst buffer. */ Dwarf_Unsigned fde_symndx; /* Symbol index for relocation. */ Dwarf_Unsigned fde_esymndx; /* End symbol index for relocation. */ Dwarf_Addr fde_eoff; /* Offset from the end symbol. */ STAILQ_ENTRY(_Dwarf_Fde) fde_next; /* Next FDE in list. */ }; struct _Dwarf_Cie { Dwarf_Debug cie_dbg; /* Ptr to containing dbg. */ Dwarf_Unsigned cie_index; /* Index of the CIE. */ Dwarf_Unsigned cie_offset; /* Offset of the CIE. */ Dwarf_Unsigned cie_length; /* Length of the CIE. */ Dwarf_Half cie_version; /* CIE version. */ uint8_t *cie_augment; /* CIE augmentation (UTF-8). */ Dwarf_Unsigned cie_ehdata; /* Optional EH Data. */ uint8_t cie_addrsize; /* Address size. (DWARF4) */ uint8_t cie_segmentsize; /* Segment size. (DWARF4) */ Dwarf_Unsigned cie_caf; /* Code alignment factor. */ Dwarf_Signed cie_daf; /* Data alignment factor. */ Dwarf_Unsigned cie_ra; /* Return address register. */ Dwarf_Unsigned cie_auglen; /* Augmentation length. */ uint8_t *cie_augdata; /* Augmentation data; */ uint8_t cie_fde_encode; /* FDE PC start/range encode. */ Dwarf_Ptr cie_initinst; /* Initial instructions. */ Dwarf_Unsigned cie_instlen; /* Length of init instructions. */ STAILQ_ENTRY(_Dwarf_Cie) cie_next; /* Next CIE in list. */ }; struct _Dwarf_FrameSec { STAILQ_HEAD(, _Dwarf_Cie) fs_cielist; /* List of CIE. */ STAILQ_HEAD(, _Dwarf_Fde) fs_fdelist; /* List of FDE. */ Dwarf_Cie *fs_ciearray; /* Array of CIE. */ Dwarf_Unsigned fs_cielen; /* Length of CIE array. */ Dwarf_Fde *fs_fdearray; /* Array of FDE.*/ Dwarf_Unsigned fs_fdelen; /* Length of FDE array. */ }; struct _Dwarf_Arange { Dwarf_ArangeSet ar_as; /* Ptr to the set it belongs to. */ Dwarf_Unsigned ar_address; /* Start PC. */ Dwarf_Unsigned ar_range; /* PC range. */ Dwarf_Unsigned ar_symndx; /* First symbol index for reloc. */ Dwarf_Unsigned ar_esymndx; /* Second symbol index for reloc. */ Dwarf_Addr ar_eoff; /* Offset from second symbol. */ STAILQ_ENTRY(_Dwarf_Arange) ar_next; /* Next arange in list. */ }; struct _Dwarf_ArangeSet { Dwarf_Unsigned as_length; /* Length of the arange set. */ Dwarf_Half as_version; /* Version of the arange set. */ Dwarf_Off as_cu_offset; /* Offset of associated CU. */ Dwarf_CU as_cu; /* Ptr to associated CU. */ Dwarf_Small as_addrsz; /* Target address size. */ Dwarf_Small as_segsz; /* Target segment size. */ STAILQ_HEAD (, _Dwarf_Arange) as_arlist; /* List of ae entries. */ STAILQ_ENTRY(_Dwarf_ArangeSet) as_next; /* Next set in list. */ }; struct _Dwarf_MacroSet { Dwarf_Macro_Details *ms_mdlist; /* Array of macinfo entries. */ Dwarf_Unsigned ms_cnt; /* Length of the array. */ STAILQ_ENTRY(_Dwarf_MacroSet) ms_next; /* Next set in list. */ }; struct _Dwarf_Rangelist { Dwarf_CU rl_cu; /* Ptr to associated CU. */ Dwarf_Unsigned rl_offset; /* Offset of the rangelist. */ Dwarf_Ranges *rl_rgarray; /* Array of ranges. */ Dwarf_Unsigned rl_rglen; /* Length of the ranges array. */ STAILQ_ENTRY(_Dwarf_Rangelist) rl_next; /* Next rangelist in list. */ }; struct _Dwarf_CU { Dwarf_Debug cu_dbg; /* Ptr to containing dbg. */ Dwarf_Off cu_offset; /* Offset to the this CU. */ uint32_t cu_length; /* Length of CU data. */ uint16_t cu_length_size; /* Size in bytes of the length field. */ uint16_t cu_version; /* DWARF version. */ uint64_t cu_abbrev_offset; /* Offset into .debug_abbrev. */ uint64_t cu_abbrev_offset_cur; /* Current abbrev offset. */ int cu_abbrev_loaded; /* Abbrev table parsed. */ uint64_t cu_abbrev_cnt; /* Abbrev entry count. */ uint64_t cu_lineno_offset; /* Offset into .debug_lineno. */ uint8_t cu_pointer_size;/* Number of bytes in pointer. */ uint8_t cu_dwarf_size; /* CU section dwarf size. */ Dwarf_Sig8 cu_type_sig; /* Type unit's signature. */ uint64_t cu_type_offset; /* Type unit's type offset. */ Dwarf_Off cu_next_offset; /* Offset to the next CU. */ uint64_t cu_1st_offset; /* First DIE offset. */ int cu_pass2; /* Two pass DIE traverse. */ Dwarf_LineInfo cu_lineinfo; /* Ptr to Dwarf_LineInfo. */ Dwarf_Abbrev cu_abbrev_hash; /* Abbrev hash table. */ Dwarf_Bool cu_is_info; /* Compilation/type unit flag. */ STAILQ_ENTRY(_Dwarf_CU) cu_next; /* Next compilation unit. */ }; typedef struct _Dwarf_Section { const char *ds_name; /* Section name. */ Dwarf_Small *ds_data; /* Section data. */ Dwarf_Unsigned ds_addr; /* Section virtual addr. */ Dwarf_Unsigned ds_size; /* Section size. */ } Dwarf_Section; typedef struct _Dwarf_P_Section { char *ds_name; /* Section name. */ Dwarf_Small *ds_data; /* Section data. */ Dwarf_Unsigned ds_size; /* Section size. */ Dwarf_Unsigned ds_cap; /* Section capacity. */ Dwarf_Unsigned ds_ndx; /* ELF section index. */ Dwarf_Unsigned ds_symndx; /* Section symbol index. (for reloc) */ STAILQ_ENTRY(_Dwarf_P_Section) ds_next; /* Next section in the list. */ } *Dwarf_P_Section; typedef struct _Dwarf_Rel_Entry { unsigned char dre_type; /* Reloc type. */ unsigned char dre_length; /* Reloc storage unit length. */ Dwarf_Unsigned dre_offset; /* Reloc storage unit offset. */ Dwarf_Unsigned dre_addend; /* Reloc addend. */ Dwarf_Unsigned dre_symndx; /* Reloc symbol index. */ const char *dre_secname; /* Refer to some debug section. */ STAILQ_ENTRY(_Dwarf_Rel_Entry) dre_next; /* Next reloc entry. */ } *Dwarf_Rel_Entry; typedef struct _Dwarf_Rel_Section { struct _Dwarf_P_Section *drs_ds; /* Ptr to actual reloc ELF section. */ struct _Dwarf_P_Section *drs_ref; /* Which debug section it refers. */ struct Dwarf_Relocation_Data_s *drs_drd; /* Reloc data array. */ STAILQ_HEAD(, _Dwarf_Rel_Entry) drs_dre; /* Reloc entry list. */ Dwarf_Unsigned drs_drecnt; /* Count of entries. */ Dwarf_Unsigned drs_size; /* Size of ELF section in bytes. */ int drs_addend; /* Elf_Rel or Elf_Rela */ STAILQ_ENTRY(_Dwarf_Rel_Section) drs_next; /* Next reloc section. */ } *Dwarf_Rel_Section; typedef struct { Elf_Data *ed_data; void *ed_alloc; } Dwarf_Elf_Data; typedef struct { Elf *eo_elf; GElf_Ehdr eo_ehdr; GElf_Shdr *eo_shdr; Dwarf_Elf_Data *eo_data; Dwarf_Unsigned eo_seccnt; size_t eo_strndx; Dwarf_Obj_Access_Methods eo_methods; } Dwarf_Elf_Object; struct _Dwarf_Debug { Dwarf_Obj_Access_Interface *dbg_iface; Dwarf_Section *dbg_section; /* Dwarf section list. */ Dwarf_Section *dbg_info_sec; /* Pointer to info section. */ Dwarf_Off dbg_info_off; /* Current info section offset. */ Dwarf_Section *dbg_types_sec; /* Pointer to type section. */ Dwarf_Off dbg_types_off; /* Current types section offset. */ Dwarf_Unsigned dbg_seccnt; /* Total number of dwarf sections. */ int dbg_mode; /* Access mode. */ int dbg_pointer_size; /* Object address size. */ int dbg_offset_size; /* DWARF offset size. */ int dbg_info_loaded; /* Flag indicating all CU loaded. */ int dbg_types_loaded; /* Flag indicating all TU loaded. */ Dwarf_Half dbg_machine; /* ELF machine architecture. */ Dwarf_Handler dbg_errhand; /* Error handler. */ Dwarf_Ptr dbg_errarg; /* Argument to the error handler. */ STAILQ_HEAD(, _Dwarf_CU) dbg_cu;/* List of compilation units. */ STAILQ_HEAD(, _Dwarf_CU) dbg_tu;/* List of type units. */ Dwarf_CU dbg_cu_current; /* Ptr to the current CU. */ Dwarf_CU dbg_tu_current; /* Ptr to the current TU. */ Dwarf_NameSec dbg_globals; /* Ptr to pubnames lookup section. */ Dwarf_NameSec dbg_pubtypes; /* Ptr to pubtypes lookup section. */ Dwarf_NameSec dbg_weaks; /* Ptr to weaknames lookup section. */ Dwarf_NameSec dbg_funcs; /* Ptr to static funcs lookup sect. */ Dwarf_NameSec dbg_vars; /* Ptr to static vars lookup sect. */ Dwarf_NameSec dbg_types; /* Ptr to types lookup section. */ Dwarf_FrameSec dbg_frame; /* Ptr to .debug_frame section. */ Dwarf_FrameSec dbg_eh_frame; /* Ptr to .eh_frame section. */ STAILQ_HEAD(, _Dwarf_ArangeSet) dbg_aslist; /* List of arange set. */ Dwarf_Arange *dbg_arange_array; /* Array of arange. */ Dwarf_Unsigned dbg_arange_cnt; /* Length of the arange array. */ char *dbg_strtab; /* Dwarf string table. */ Dwarf_Unsigned dbg_strtab_cap; /* Dwarf string table capacity. */ Dwarf_Unsigned dbg_strtab_size; /* Dwarf string table size. */ STAILQ_HEAD(, _Dwarf_MacroSet) dbg_mslist; /* List of macro set. */ STAILQ_HEAD(, _Dwarf_Rangelist) dbg_rllist; /* List of rangelist. */ uint64_t (*read)(uint8_t *, uint64_t *, int); void (*write)(uint8_t *, uint64_t *, uint64_t, int); int (*write_alloc)(uint8_t **, uint64_t *, uint64_t *, uint64_t, int, Dwarf_Error *); uint64_t (*decode)(uint8_t **, int); Dwarf_Half dbg_frame_rule_table_size; Dwarf_Half dbg_frame_rule_initial_value; Dwarf_Half dbg_frame_cfa_value; Dwarf_Half dbg_frame_same_value; Dwarf_Half dbg_frame_undefined_value; Dwarf_Regtable3 *dbg_internal_reg_table; /* * Fields used by libdwarf producer. */ Dwarf_Unsigned dbgp_flags; Dwarf_Unsigned dbgp_isa; Dwarf_Callback_Func dbgp_func; Dwarf_Callback_Func_b dbgp_func_b; Dwarf_Die dbgp_root_die; STAILQ_HEAD(, _Dwarf_Die) dbgp_dielist; STAILQ_HEAD(, _Dwarf_P_Expr) dbgp_pelist; Dwarf_LineInfo dbgp_lineinfo; Dwarf_ArangeSet dbgp_as; Dwarf_Macro_Details *dbgp_mdlist; Dwarf_Unsigned dbgp_mdcnt; STAILQ_HEAD(, _Dwarf_Cie) dbgp_cielist; STAILQ_HEAD(, _Dwarf_Fde) dbgp_fdelist; Dwarf_Unsigned dbgp_cielen; Dwarf_Unsigned dbgp_fdelen; Dwarf_NameTbl dbgp_pubs; Dwarf_NameTbl dbgp_weaks; Dwarf_NameTbl dbgp_funcs; Dwarf_NameTbl dbgp_types; Dwarf_NameTbl dbgp_vars; STAILQ_HEAD(, _Dwarf_P_Section) dbgp_seclist; Dwarf_Unsigned dbgp_seccnt; Dwarf_P_Section dbgp_secpos; Dwarf_P_Section dbgp_info; STAILQ_HEAD(, _Dwarf_Rel_Section) dbgp_drslist; Dwarf_Unsigned dbgp_drscnt; Dwarf_Rel_Section dbgp_drspos; }; /* * Internal function prototypes. */ int _dwarf_abbrev_add(Dwarf_CU, uint64_t, uint64_t, uint8_t, uint64_t, Dwarf_Abbrev *, Dwarf_Error *); void _dwarf_abbrev_cleanup(Dwarf_CU); int _dwarf_abbrev_find(Dwarf_CU, uint64_t, Dwarf_Abbrev *, Dwarf_Error *); int _dwarf_abbrev_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_abbrev_parse(Dwarf_Debug, Dwarf_CU, Dwarf_Unsigned *, Dwarf_Abbrev *, Dwarf_Error *); int _dwarf_add_AT_dataref(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, const char *, Dwarf_P_Attribute *, Dwarf_Error *); int _dwarf_add_string_attr(Dwarf_P_Die, Dwarf_P_Attribute *, Dwarf_Half, char *, Dwarf_Error *); int _dwarf_alloc(Dwarf_Debug *, int, Dwarf_Error *); void _dwarf_arange_cleanup(Dwarf_Debug); int _dwarf_arange_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_arange_init(Dwarf_Debug, Dwarf_Error *); void _dwarf_arange_pro_cleanup(Dwarf_P_Debug); int _dwarf_attr_alloc(Dwarf_Die, Dwarf_Attribute *, Dwarf_Error *); Dwarf_Attribute _dwarf_attr_find(Dwarf_Die, Dwarf_Half); int _dwarf_attr_gen(Dwarf_P_Debug, Dwarf_P_Section, Dwarf_Rel_Section, Dwarf_CU, Dwarf_Die, int, Dwarf_Error *); int _dwarf_attr_init(Dwarf_Debug, Dwarf_Section *, uint64_t *, int, Dwarf_CU, Dwarf_Die, Dwarf_AttrDef, uint64_t, int, Dwarf_Error *); int _dwarf_attrdef_add(Dwarf_Debug, Dwarf_Abbrev, uint64_t, uint64_t, uint64_t, Dwarf_AttrDef *, Dwarf_Error *); uint64_t _dwarf_decode_lsb(uint8_t **, int); uint64_t _dwarf_decode_msb(uint8_t **, int); int64_t _dwarf_decode_sleb128(uint8_t **); uint64_t _dwarf_decode_uleb128(uint8_t **); void _dwarf_deinit(Dwarf_Debug); int _dwarf_die_alloc(Dwarf_Debug, Dwarf_Die *, Dwarf_Error *); int _dwarf_die_count_links(Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die); Dwarf_Die _dwarf_die_find(Dwarf_Die, Dwarf_Unsigned); int _dwarf_die_gen(Dwarf_P_Debug, Dwarf_CU, Dwarf_Rel_Section, Dwarf_Error *); void _dwarf_die_link(Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die); int _dwarf_die_parse(Dwarf_Debug, Dwarf_Section *, Dwarf_CU, int, uint64_t, uint64_t, Dwarf_Die *, int, Dwarf_Error *); void _dwarf_die_pro_cleanup(Dwarf_P_Debug); void _dwarf_elf_deinit(Dwarf_Debug); int _dwarf_elf_init(Dwarf_Debug, Elf *, Dwarf_Error *); int _dwarf_elf_load_section(void *, Dwarf_Half, Dwarf_Small **, int *); Dwarf_Endianness _dwarf_elf_get_byte_order(void *); Dwarf_Small _dwarf_elf_get_length_size(void *); Dwarf_Small _dwarf_elf_get_pointer_size(void *); Dwarf_Unsigned _dwarf_elf_get_section_count(void *); int _dwarf_elf_get_section_info(void *, Dwarf_Half, Dwarf_Obj_Access_Section *, int *); void _dwarf_expr_cleanup(Dwarf_P_Debug); int _dwarf_expr_into_block(Dwarf_P_Expr, Dwarf_Error *); Dwarf_Section *_dwarf_find_next_types_section(Dwarf_Debug, Dwarf_Section *); Dwarf_Section *_dwarf_find_section(Dwarf_Debug, const char *); void _dwarf_frame_cleanup(Dwarf_Debug); int _dwarf_frame_fde_add_inst(Dwarf_P_Fde, Dwarf_Small, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); int _dwarf_frame_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_frame_get_fop(Dwarf_Debug, uint8_t, uint8_t *, Dwarf_Unsigned, Dwarf_Frame_Op **, Dwarf_Signed *, Dwarf_Error *); int _dwarf_frame_get_internal_table(Dwarf_Fde, Dwarf_Addr, Dwarf_Regtable3 **, Dwarf_Addr *, Dwarf_Error *); int _dwarf_frame_interal_table_init(Dwarf_Debug, Dwarf_Error *); void _dwarf_frame_params_init(Dwarf_Debug); void _dwarf_frame_pro_cleanup(Dwarf_P_Debug); int _dwarf_frame_regtable_copy(Dwarf_Debug, Dwarf_Regtable3 **, Dwarf_Regtable3 *, Dwarf_Error *); int _dwarf_frame_section_load(Dwarf_Debug, Dwarf_Error *); int _dwarf_frame_section_load_eh(Dwarf_Debug, Dwarf_Error *); int _dwarf_generate_sections(Dwarf_P_Debug, Dwarf_Error *); Dwarf_Unsigned _dwarf_get_reloc_type(Dwarf_P_Debug, int); int _dwarf_get_reloc_size(Dwarf_Debug, Dwarf_Unsigned); void _dwarf_info_cleanup(Dwarf_Debug); int _dwarf_info_first_cu(Dwarf_Debug, Dwarf_Error *); int _dwarf_info_first_tu(Dwarf_Debug, Dwarf_Error *); int _dwarf_info_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_info_load(Dwarf_Debug, Dwarf_Bool, Dwarf_Bool, Dwarf_Error *); int _dwarf_info_next_cu(Dwarf_Debug, Dwarf_Error *); int _dwarf_info_next_tu(Dwarf_Debug, Dwarf_Error *); void _dwarf_info_pro_cleanup(Dwarf_P_Debug); int _dwarf_init(Dwarf_Debug, Dwarf_Unsigned, Dwarf_Handler, Dwarf_Ptr, Dwarf_Error *); int _dwarf_lineno_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_lineno_init(Dwarf_Die, uint64_t, Dwarf_Error *); void _dwarf_lineno_cleanup(Dwarf_LineInfo); void _dwarf_lineno_pro_cleanup(Dwarf_P_Debug); int _dwarf_loc_fill_locdesc(Dwarf_Debug, Dwarf_Locdesc *, uint8_t *, uint64_t, uint8_t, uint8_t, uint8_t, Dwarf_Error *); int _dwarf_loc_fill_locexpr(Dwarf_Debug, Dwarf_Locdesc **, uint8_t *, uint64_t, uint8_t, uint8_t, uint8_t, Dwarf_Error *); int _dwarf_loc_add(Dwarf_Die, Dwarf_Attribute, Dwarf_Error *); int _dwarf_loc_expr_add_atom(Dwarf_Debug, uint8_t *, uint8_t *, Dwarf_Small, Dwarf_Unsigned, Dwarf_Unsigned, int *, Dwarf_Error *); int _dwarf_loclist_find(Dwarf_Debug, Dwarf_CU, uint64_t, Dwarf_Locdesc ***, Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *); void _dwarf_macinfo_cleanup(Dwarf_Debug); int _dwarf_macinfo_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_macinfo_init(Dwarf_Debug, Dwarf_Error *); void _dwarf_macinfo_pro_cleanup(Dwarf_P_Debug); int _dwarf_nametbl_init(Dwarf_Debug, Dwarf_NameSec *, Dwarf_Section *, Dwarf_Error *); void _dwarf_nametbl_cleanup(Dwarf_NameSec *); int _dwarf_nametbl_gen(Dwarf_P_Debug, const char *, Dwarf_NameTbl, Dwarf_Error *); void _dwarf_nametbl_pro_cleanup(Dwarf_NameTbl *); int _dwarf_pro_callback(Dwarf_P_Debug, char *, int, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned *, int *); Dwarf_P_Section _dwarf_pro_find_section(Dwarf_P_Debug, const char *); int _dwarf_ranges_add(Dwarf_Debug, Dwarf_CU, uint64_t, Dwarf_Rangelist *, Dwarf_Error *); void _dwarf_ranges_cleanup(Dwarf_Debug); int _dwarf_ranges_find(Dwarf_Debug, uint64_t, Dwarf_Rangelist *); uint64_t _dwarf_read_lsb(uint8_t *, uint64_t *, int); uint64_t _dwarf_read_msb(uint8_t *, uint64_t *, int); int64_t _dwarf_read_sleb128(uint8_t *, uint64_t *); uint64_t _dwarf_read_uleb128(uint8_t *, uint64_t *); char *_dwarf_read_string(void *, Dwarf_Unsigned, uint64_t *); uint8_t *_dwarf_read_block(void *, uint64_t *, uint64_t); int _dwarf_reloc_section_finalize(Dwarf_P_Debug, Dwarf_Rel_Section, Dwarf_Error *); int _dwarf_reloc_entry_add(Dwarf_P_Debug, Dwarf_Rel_Section, Dwarf_P_Section, unsigned char, unsigned char, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, const char *, Dwarf_Error *); int _dwarf_reloc_entry_add_pair(Dwarf_P_Debug, Dwarf_Rel_Section, Dwarf_P_Section, unsigned char, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); void _dwarf_reloc_cleanup(Dwarf_P_Debug); int _dwarf_reloc_gen(Dwarf_P_Debug, Dwarf_Error *); int _dwarf_reloc_section_gen(Dwarf_P_Debug, Dwarf_Rel_Section, Dwarf_Error *); int _dwarf_reloc_section_init(Dwarf_P_Debug, Dwarf_Rel_Section *, Dwarf_P_Section, Dwarf_Error *); void _dwarf_reloc_section_free(Dwarf_P_Debug, Dwarf_Rel_Section *); void _dwarf_section_cleanup(Dwarf_P_Debug); int _dwarf_section_callback(Dwarf_P_Debug, Dwarf_P_Section, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); void _dwarf_section_free(Dwarf_P_Debug, Dwarf_P_Section *); int _dwarf_section_init(Dwarf_P_Debug, Dwarf_P_Section *, const char *, int, Dwarf_Error *); void _dwarf_set_error(Dwarf_Debug, Dwarf_Error *, int, int, const char *, int); int _dwarf_strtab_add(Dwarf_Debug, char *, uint64_t *, Dwarf_Error *); void _dwarf_strtab_cleanup(Dwarf_Debug); int _dwarf_strtab_gen(Dwarf_P_Debug, Dwarf_Error *); char *_dwarf_strtab_get_table(Dwarf_Debug); int _dwarf_strtab_init(Dwarf_Debug, Dwarf_Error *); void _dwarf_type_unit_cleanup(Dwarf_Debug); void _dwarf_write_block(void *, uint64_t *, uint8_t *, uint64_t); int _dwarf_write_block_alloc(uint8_t **, uint64_t *, uint64_t *, uint8_t *, uint64_t, Dwarf_Error *); void _dwarf_write_lsb(uint8_t *, uint64_t *, uint64_t, int); int _dwarf_write_lsb_alloc(uint8_t **, uint64_t *, uint64_t *, uint64_t, int, Dwarf_Error *); void _dwarf_write_msb(uint8_t *, uint64_t *, uint64_t, int); int _dwarf_write_msb_alloc(uint8_t **, uint64_t *, uint64_t *, uint64_t, int, Dwarf_Error *); void _dwarf_write_padding(void *, uint64_t *, uint8_t, uint64_t); int _dwarf_write_padding_alloc(uint8_t **, uint64_t *, uint64_t *, uint8_t, uint64_t, Dwarf_Error *); void _dwarf_write_string(void *, uint64_t *, char *); int _dwarf_write_string_alloc(uint8_t **, uint64_t *, uint64_t *, char *, Dwarf_Error *); int _dwarf_write_sleb128(uint8_t *, uint8_t *, int64_t); int _dwarf_write_sleb128_alloc(uint8_t **, uint64_t *, uint64_t *, int64_t, Dwarf_Error *); int _dwarf_write_uleb128(uint8_t *, uint8_t *, uint64_t); int _dwarf_write_uleb128_alloc(uint8_t **, uint64_t *, uint64_t *, uint64_t, Dwarf_Error *); #endif /* !__LIBDWARF_H_ */ Index: head/contrib/elftoolchain/libdwarf/libdwarf.h =================================================================== --- head/contrib/elftoolchain/libdwarf/libdwarf.h (revision 280931) +++ head/contrib/elftoolchain/libdwarf/libdwarf.h (revision 280932) @@ -1,836 +1,840 @@ /*- * Copyright (c) 2007 John Birrell (jb@freebsd.org) * Copyright (c) 2009-2011,2014 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: libdwarf.h 3149 2015-02-15 19:00:06Z emaste $ + * $Id: libdwarf.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef _LIBDWARF_H_ #define _LIBDWARF_H_ #include typedef int Dwarf_Bool; typedef off_t Dwarf_Off; typedef uint64_t Dwarf_Unsigned; typedef uint16_t Dwarf_Half; typedef uint8_t Dwarf_Small; typedef int64_t Dwarf_Signed; typedef uint64_t Dwarf_Addr; typedef void *Dwarf_Ptr; typedef struct _Dwarf_Abbrev *Dwarf_Abbrev; typedef struct _Dwarf_Arange *Dwarf_Arange; typedef struct _Dwarf_ArangeSet *Dwarf_ArangeSet; typedef struct _Dwarf_Attribute *Dwarf_Attribute; typedef struct _Dwarf_Attribute *Dwarf_P_Attribute; typedef struct _Dwarf_AttrDef *Dwarf_AttrDef; typedef struct _Dwarf_Cie *Dwarf_Cie; typedef struct _Dwarf_Cie *Dwarf_P_Cie; typedef struct _Dwarf_Debug *Dwarf_Debug; typedef struct _Dwarf_Debug *Dwarf_P_Debug; typedef struct _Dwarf_Die *Dwarf_Die; typedef struct _Dwarf_Die *Dwarf_P_Die; typedef struct _Dwarf_Fde *Dwarf_Fde; typedef struct _Dwarf_Fde *Dwarf_P_Fde; typedef struct _Dwarf_FrameSec *Dwarf_FrameSec; typedef struct _Dwarf_Line *Dwarf_Line; typedef struct _Dwarf_LineFile *Dwarf_LineFile; typedef struct _Dwarf_LineInfo *Dwarf_LineInfo; typedef struct _Dwarf_MacroSet *Dwarf_MacroSet; typedef struct _Dwarf_NamePair *Dwarf_NamePair; typedef struct _Dwarf_NamePair *Dwarf_Func; typedef struct _Dwarf_NamePair *Dwarf_Global; typedef struct _Dwarf_NamePair *Dwarf_Type; typedef struct _Dwarf_NamePair *Dwarf_Var; typedef struct _Dwarf_NamePair *Dwarf_Weak; typedef struct _Dwarf_NameTbl *Dwarf_NameTbl; typedef struct _Dwarf_NameSec *Dwarf_NameSec; typedef struct _Dwarf_P_Expr *Dwarf_P_Expr; typedef struct _Dwarf_Rangelist *Dwarf_Rangelist; typedef enum { DW_OBJECT_MSB, DW_OBJECT_LSB } Dwarf_Endianness; typedef struct { Dwarf_Addr addr; Dwarf_Unsigned size; const char *name; } Dwarf_Obj_Access_Section; typedef struct { int (*get_section_info)(void *_obj, Dwarf_Half _index, Dwarf_Obj_Access_Section *_ret_section, int *_error); Dwarf_Endianness (*get_byte_order)(void *_obj); Dwarf_Small (*get_length_size)(void *_obj); Dwarf_Small (*get_pointer_size)(void *_obj); Dwarf_Unsigned (*get_section_count)(void *_obj); int (*load_section)(void *_obj, Dwarf_Half _index, Dwarf_Small **_ret_data, int *_error); } Dwarf_Obj_Access_Methods; typedef struct { void *object; const Dwarf_Obj_Access_Methods *methods; } Dwarf_Obj_Access_Interface; typedef int (*Dwarf_Callback_Func)(char *_name, int _size, Dwarf_Unsigned _type, Dwarf_Unsigned _flags, Dwarf_Unsigned _link, Dwarf_Unsigned _info, int *_index, int *_error); typedef int (*Dwarf_Callback_Func_b)(char *_name, int _size, Dwarf_Unsigned _type, Dwarf_Unsigned _flags, Dwarf_Unsigned _link, Dwarf_Unsigned _info, Dwarf_Unsigned *_index, int *_error); typedef Dwarf_Unsigned Dwarf_Tag; typedef struct { Dwarf_Small lr_atom; Dwarf_Unsigned lr_number; Dwarf_Unsigned lr_number2; Dwarf_Unsigned lr_offset; } Dwarf_Loc; typedef struct { Dwarf_Addr ld_lopc; Dwarf_Addr ld_hipc; Dwarf_Half ld_cents; Dwarf_Loc *ld_s; } Dwarf_Locdesc; typedef struct { char signature[8]; } Dwarf_Sig8; typedef struct { Dwarf_Unsigned bl_len; Dwarf_Ptr bl_data; } Dwarf_Block; enum Dwarf_Ranges_Entry_Type { DW_RANGES_ENTRY, DW_RANGES_ADDRESS_SELECTION, DW_RANGES_END }; typedef struct { Dwarf_Unsigned dwr_addr1; Dwarf_Unsigned dwr_addr2; enum Dwarf_Ranges_Entry_Type dwr_type; } Dwarf_Ranges; enum Dwarf_Form_Class { DW_FORM_CLASS_UNKNOWN, DW_FORM_CLASS_ADDRESS, DW_FORM_CLASS_BLOCK, DW_FORM_CLASS_CONSTANT, DW_FORM_CLASS_EXPRLOC, DW_FORM_CLASS_FLAG, DW_FORM_CLASS_LINEPTR, DW_FORM_CLASS_LOCLISTPTR, DW_FORM_CLASS_MACPTR, DW_FORM_CLASS_RANGELISTPTR, DW_FORM_CLASS_REFERENCE, DW_FORM_CLASS_STRING }; #ifndef DW_FRAME_HIGHEST_NORMAL_REGISTER #define DW_FRAME_HIGHEST_NORMAL_REGISTER 63 #endif #define DW_FRAME_RA_COL (DW_FRAME_HIGHEST_NORMAL_REGISTER + 1) #define DW_FRAME_STATIC_LINK (DW_FRAME_HIGHEST_NORMAL_REGISTER + 2) #ifndef DW_FRAME_LAST_REG_NUM #define DW_FRAME_LAST_REG_NUM (DW_FRAME_HIGHEST_NORMAL_REGISTER + 3) #endif #ifndef DW_FRAME_REG_INITIAL_VALUE #define DW_FRAME_REG_INITIAL_VALUE DW_FRAME_SAME_VAL #endif #define DW_FRAME_UNDEFINED_VAL 1034 #define DW_FRAME_SAME_VAL 1035 #define DW_FRAME_CFA_COL3 1436 #define DW_EXPR_OFFSET 0 #define DW_EXPR_VAL_OFFSET 1 #define DW_EXPR_EXPRESSION 2 #define DW_EXPR_VAL_EXPRESSION 3 /* * Frame operation only for DWARF 2. */ #define DW_FRAME_CFA_COL 0 typedef struct { Dwarf_Small fp_base_op; Dwarf_Small fp_extended_op; Dwarf_Half fp_register; Dwarf_Signed fp_offset; Dwarf_Off fp_instr_offset; } Dwarf_Frame_Op; #ifndef DW_REG_TABLE_SIZE #define DW_REG_TABLE_SIZE 66 #endif typedef struct { struct { Dwarf_Small dw_offset_relevant; Dwarf_Half dw_regnum; Dwarf_Addr dw_offset; } rules[DW_REG_TABLE_SIZE]; } Dwarf_Regtable; /* * Frame operation for DWARF 3 and DWARF 2. */ typedef struct { Dwarf_Small fp_base_op; Dwarf_Small fp_extended_op; Dwarf_Half fp_register; Dwarf_Unsigned fp_offset_or_block_len; Dwarf_Small *fp_expr_block; Dwarf_Off fp_instr_offset; } Dwarf_Frame_Op3; typedef struct { Dwarf_Small dw_offset_relevant; Dwarf_Small dw_value_type; Dwarf_Half dw_regnum; Dwarf_Unsigned dw_offset_or_block_len; Dwarf_Ptr dw_block_ptr; } Dwarf_Regtable_Entry3; typedef struct { Dwarf_Regtable_Entry3 rt3_cfa_rule; Dwarf_Half rt3_reg_table_size; Dwarf_Regtable_Entry3 *rt3_rules; } Dwarf_Regtable3; typedef struct { Dwarf_Off dmd_offset; Dwarf_Small dmd_type; Dwarf_Signed dmd_lineno; Dwarf_Signed dmd_fileindex; char *dmd_macro; } Dwarf_Macro_Details; /* * Symbols denoting allocation types, for use with dwarf_dealloc(3). */ enum Dwarf_Allocation_Type { DW_DLA_ABBREV, DW_DLA_ADDR, DW_DLA_ARANGE, DW_DLA_ATTR, DW_DLA_BLOCK, DW_DLA_BOUNDS, DW_DLA_CIE, DW_DLA_DEBUG, DW_DLA_DIE, DW_DLA_ELLIST, DW_DLA_ERROR, DW_DLA_FDE, DW_DLA_FRAME_BLOCK, DW_DLA_FRAME_OP, DW_DLA_FUNC, DW_DLA_GLOBAL, DW_DLA_LINE, DW_DLA_LINEBUF, DW_DLA_LIST, DW_DLA_LOC, DW_DLA_LOCDESC, DW_DLA_LOC_BLOCK, DW_DLA_RANGES, DW_DLA_STRING, DW_DLA_SUBSCR, DW_DLA_TYPE, DW_DLA_TYPENAME, DW_DLA_VAR, DW_DLA_WEAK }; /* * Relocation Type. */ enum Dwarf_Rel_Type { dwarf_drt_none = 0, dwarf_drt_data_reloc, dwarf_drt_segment_rel, dwarf_drt_first_of_length_pair, dwarf_drt_second_of_length_pair }; /* * Relocation Entry. */ typedef struct Dwarf_Relocation_Data_s { unsigned char drd_type; unsigned char drd_length; Dwarf_Unsigned drd_offset; Dwarf_Unsigned drd_symbol_index; } *Dwarf_Relocation_Data; #define DWARF_DRD_BUFFER_VERSION 2 /* * Error numbers which are specific to this implementation. */ enum { DW_DLE_NONE, /* No error. */ DW_DLE_ERROR, /* An error! */ DW_DLE_ARGUMENT, /* Invalid argument. */ DW_DLE_DEBUG_INFO_NULL, /* Debug info NULL. */ DW_DLE_NO_ENTRY, /* No entry. */ DW_DLE_MEMORY, /* Insufficient memory. */ DW_DLE_ELF, /* ELF error. */ DW_DLE_CU_LENGTH_ERROR, /* Invalid compilation unit data. */ DW_DLE_VERSION_STAMP_ERROR, /* Invalid version. */ DW_DLE_DEBUG_ABBREV_NULL, /* Abbrev not found. */ DW_DLE_DIE_NO_CU_CONTEXT, /* No current compilation unit. */ DW_DLE_LOC_EXPR_BAD, /* Invalid location expression. */ DW_DLE_EXPR_LENGTH_BAD, /* Invalid DWARF expression. */ DW_DLE_DEBUG_LOC_SECTION_SHORT, /* Loclist section too short. */ DW_DLE_ATTR_FORM_BAD, /* Invalid attribute form. */ DW_DLE_DEBUG_LINE_LENGTH_BAD, /* Line info section too short. */ DW_DLE_LINE_FILE_NUM_BAD, /* Invalid file number. */ DW_DLE_DIR_INDEX_BAD, /* Invalid dir index. */ DW_DLE_DEBUG_FRAME_LENGTH_BAD, /* Frame section too short. */ DW_DLE_NO_CIE_FOR_FDE, /* CIE not found for certain FDE. */ DW_DLE_FRAME_AUGMENTATION_UNKNOWN, /* Unknown CIE augmentation. */ DW_DLE_FRAME_INSTR_EXEC_ERROR, /* Frame instruction exec error. */ DW_DLE_FRAME_VERSION_BAD, /* Invalid frame section version. */ DW_DLE_FRAME_TABLE_COL_BAD, /* Invalid table column. */ DW_DLE_DF_REG_NUM_TOO_HIGH, /* Insufficient regtable space. */ DW_DLE_PC_NOT_IN_FDE_RANGE, /* PC requested not in the FDE range. */ DW_DLE_ARANGE_OFFSET_BAD, /* Invalid arange offset. */ DW_DLE_DEBUG_MACRO_INCONSISTENT,/* Invalid macinfo data. */ DW_DLE_ELF_SECT_ERR, /* Application callback failed. */ DW_DLE_NUM /* Max error number. */ }; /* * Mapping of SGI libdwarf error codes for comptibility. */ #define DW_DLE_DBG_ALLOC DW_DLE_MEMORY #define DW_DLE_ALLOC_FAIL DW_DLE_MEMORY #define DW_DLE_SECT_ALLOC DW_DLE_MEMORY #define DW_DLE_FILE_ENTRY_ALLOC DW_DLE_MEMORY #define DW_DLE_LINE_ALLOC DW_DLE_MEMORY #define DW_DLE_FPGM_ALLOC DW_DLE_MEMORY #define DW_DLE_INCDIR_ALLOC DW_DLE_MEMORY #define DW_DLE_STRING_ALLOC DW_DLE_MEMORY #define DW_DLE_CHUNK_ALLOC DW_DLE_MEMORY #define DW_DLE_CIE_ALLOC DW_DLE_MEMORY #define DW_DLE_FDE_ALLOC DW_DLE_MEMORY #define DW_DLE_CIE_OFFS_ALLOC DW_DLE_MEMORY #define DW_DLE_DIE_ALLOC DW_DLE_MEMORY #define DW_DLE_ATTR_ALLOC DW_DLE_MEMORY #define DW_DLE_ABBREV_ALLOC DW_DLE_MEMORY #define DW_DLE_ADDR_ALLOC DW_DLE_MEMORY #define DW_DLE_REL_ALLOC DW_DLE_MEMORY #define DW_DLE_MACINFO_MALLOC_FAIL DW_DLE_MEMORY #define DW_DLE_DEBUG_MACRO_MALLOC_SPACE DW_DLE_MEMORY #define DW_DLE_DF_ALLOC_FAIL DW_DLE_MEMORY #define DW_DLE_RELOC_SECTION_MALLOC_FAIL DW_DLE_MEMORY #define DW_DLE_DBG_NULL DW_DLE_ARGUMENT #define DW_DLE_DIE_NULL DW_DLE_ARGUMENT #define DW_DLE_FDE_NULL DW_DLE_ARGUMENT #define DW_DLE_CIE_NULL DW_DLE_ARGUMENT #define DW_DLE_ATTR_NULL DW_DLE_ARGUMENT #define DW_DLE_GLOBAL_NULL DW_DLE_ARGUMENT #define DW_DLE_ARANGES_NULL DW_DLE_ARGUMENT #define DW_DLE_ARANGE_NULL DW_DLE_ARGUMENT #define DW_DLE_EXPR_NULL DW_DLE_ARGUMENT #define DW_DLE_FUNC_NULL DW_DLE_ARGUMENT #define DW_DLE_TYPE_NULL DW_DLE_ARGUMENT #define DW_DLE_VAR_NULL DW_DLE_ARGUMENT #define DW_DLE_WEAK_NULL DW_DLE_ARGUMENT #define DW_DLE_ELF_BEGIN_ERROR DW_DLE_ELF #define DW_DLE_ELF_GETEHDR_ERROR DW_DLE_ELF #define DW_DLE_ELF_GETSHDR_ERROR DW_DLE_ELF #define DW_DLE_ELF_STRPTR_ERROR DW_DLE_ELF #define DW_DLE_ELF_SECT_ERROR DW_DLE_ELF #define DW_DLE_ELF_GETIDENT_ERROR DW_DLE_ELF typedef struct _Dwarf_Error { int err_error; /* DWARF error. */ int err_elferror; /* ELF error. */ const char *err_func; /* Function name where error occurred. */ int err_line; /* Line number where error occurred. */ char err_msg[1024]; /* Formatted error message. */ } Dwarf_Error; /* * Dwarf error handler. */ typedef void (*Dwarf_Handler)(Dwarf_Error, Dwarf_Ptr); #define dwarf_errno(error) error.err_error #define dwarf_errmsg(error) dwarf_errmsg_(&error) /* * Return values which have to be compatible with other * implementations of libdwarf. */ #define DW_DLV_NO_ENTRY -1 #define DW_DLV_OK 0 #define DW_DLV_ERROR 1 #define DW_DLV_BADADDR NULL #define DW_DLV_NOCOUNT ((Dwarf_Signed) -1) /* * Access modes. */ #define DW_DLC_READ 0x0001 #define DW_DLC_WRITE 0x0002 #define DW_DLC_RDWR 0x0004 /* * Flags used by libdwarf producer. */ #define DW_DLC_SIZE_64 0x40000000 #define DW_DLC_SIZE_32 0x20000000 #define DW_DLC_OFFSET_SIZE_64 0x10000000 #define DW_DLC_ISA_MIPS 0x80000000 #define DW_DLC_ISA_IA64 0x01000000 #define DW_DLC_STREAM_RELOCATIONS 0x02000000 #define DW_DLC_SYMBOLIC_RELOCATIONS 0x04000000 #define DW_DLC_TARGET_BIGENDIAN 0x08000000 #define DW_DLC_TARGET_LITTLEENDIAN 0x00100000 /* * Instruction set architectures supported by this implementation. */ enum Dwarf_ISA { DW_ISA_ARM, DW_ISA_IA64, DW_ISA_MIPS, DW_ISA_PPC, DW_ISA_SPARC, DW_ISA_X86, DW_ISA_X86_64, DW_ISA_AARCH64, DW_ISA_MAX }; /* Function prototype definitions. */ -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif Dwarf_P_Attribute dwarf_add_AT_comp_dir(Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_const_value_signedint(Dwarf_P_Die, Dwarf_Signed, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_const_value_string(Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_const_value_unsignedint(Dwarf_P_Die, Dwarf_Unsigned, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_dataref(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_flag(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Small, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_location_expr(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_P_Expr, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_name(Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_producer(Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_ref_address(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_reference(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_P_Die, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_signed_const(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Signed, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_string(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, char *, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_targ_address(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_targ_address_b(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_P_Attribute dwarf_add_AT_unsigned_const(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Half, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_arange(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Error *); Dwarf_Unsigned dwarf_add_arange_b(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Error *); Dwarf_Unsigned dwarf_add_die_to_debug(Dwarf_P_Debug, Dwarf_P_Die, Dwarf_Error *); Dwarf_Unsigned dwarf_add_directory_decl(Dwarf_P_Debug, char *, Dwarf_Error *); Dwarf_Unsigned dwarf_add_expr_addr(Dwarf_P_Expr, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Error *); Dwarf_Unsigned dwarf_add_expr_addr_b(Dwarf_P_Expr, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_expr_gen(Dwarf_P_Expr, Dwarf_Small, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_P_Fde dwarf_add_fde_inst(Dwarf_P_Fde, Dwarf_Small, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_file_decl(Dwarf_P_Debug, char *, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_frame_cie(Dwarf_P_Debug, char *, Dwarf_Small, Dwarf_Small, Dwarf_Small, Dwarf_Ptr, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_frame_fde(Dwarf_P_Debug, Dwarf_P_Fde, Dwarf_P_Die, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); Dwarf_Unsigned dwarf_add_frame_fde_b(Dwarf_P_Debug, Dwarf_P_Fde, Dwarf_P_Die, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Error *); Dwarf_Unsigned dwarf_add_funcname(Dwarf_P_Debug, Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_Unsigned dwarf_add_line_entry(Dwarf_P_Debug, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Bool, Dwarf_Bool, Dwarf_Error *); Dwarf_Unsigned dwarf_add_pubname(Dwarf_P_Debug, Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_Unsigned dwarf_add_typename(Dwarf_P_Debug, Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_Unsigned dwarf_add_varname(Dwarf_P_Debug, Dwarf_P_Die, char *, Dwarf_Error *); Dwarf_Unsigned dwarf_add_weakname(Dwarf_P_Debug, Dwarf_P_Die, char *, Dwarf_Error *); int dwarf_arrayorder(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_attr(Dwarf_Die, Dwarf_Half, Dwarf_Attribute *, Dwarf_Error *); int dwarf_attrlist(Dwarf_Die, Dwarf_Attribute **, Dwarf_Signed *, Dwarf_Error *); int dwarf_attroffset(Dwarf_Attribute, Dwarf_Off *, Dwarf_Error *); int dwarf_attrval_flag(Dwarf_Die, Dwarf_Half, Dwarf_Bool *, Dwarf_Error *); int dwarf_attrval_signed(Dwarf_Die, Dwarf_Half, Dwarf_Signed *, Dwarf_Error *); int dwarf_attrval_string(Dwarf_Die, Dwarf_Half, const char **, Dwarf_Error *); int dwarf_attrval_unsigned(Dwarf_Die, Dwarf_Half, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_bitoffset(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_bitsize(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_bytesize(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_child(Dwarf_Die, Dwarf_Die *, Dwarf_Error *); void dwarf_dealloc(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned); int dwarf_def_macro(Dwarf_P_Debug, Dwarf_Unsigned, char *, char *, Dwarf_Error *); int dwarf_die_CU_offset(Dwarf_Die, Dwarf_Off *, Dwarf_Error *); int dwarf_die_CU_offset_range(Dwarf_Die, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_die_abbrev_code(Dwarf_Die); Dwarf_P_Die dwarf_die_link(Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_Error *); int dwarf_diename(Dwarf_Die, char **, Dwarf_Error *); int dwarf_dieoffset(Dwarf_Die, Dwarf_Off *, Dwarf_Error *); int dwarf_elf_init(Elf *, int, Dwarf_Handler, Dwarf_Ptr, Dwarf_Debug *, Dwarf_Error *); int dwarf_end_macro_file(Dwarf_P_Debug, Dwarf_Error *); const char *dwarf_errmsg_(Dwarf_Error *); int dwarf_expand_frame_instructions(Dwarf_Cie, Dwarf_Ptr, Dwarf_Unsigned, Dwarf_Frame_Op **, Dwarf_Signed *, Dwarf_Error *); Dwarf_Unsigned dwarf_expr_current_offset(Dwarf_P_Expr, Dwarf_Error *); Dwarf_Addr dwarf_expr_into_block(Dwarf_P_Expr, Dwarf_Unsigned *, Dwarf_Error *); Dwarf_P_Fde dwarf_fde_cfa_offset(Dwarf_P_Fde, Dwarf_Unsigned, Dwarf_Signed, Dwarf_Error *); void dwarf_fde_cie_list_dealloc(Dwarf_Debug, Dwarf_Cie *, Dwarf_Signed, Dwarf_Fde *, Dwarf_Signed); char *dwarf_find_macro_value_start(char *); int dwarf_finish(Dwarf_Debug, Dwarf_Error *); int dwarf_formaddr(Dwarf_Attribute, Dwarf_Addr *, Dwarf_Error *); int dwarf_formblock(Dwarf_Attribute, Dwarf_Block **, Dwarf_Error *); int dwarf_formexprloc(Dwarf_Attribute, Dwarf_Unsigned *, Dwarf_Ptr *, Dwarf_Error *); int dwarf_formflag(Dwarf_Attribute, Dwarf_Bool *, Dwarf_Error *); int dwarf_formref(Dwarf_Attribute, Dwarf_Off *, Dwarf_Error *); int dwarf_formsdata(Dwarf_Attribute, Dwarf_Signed *, Dwarf_Error *); int dwarf_formsig8(Dwarf_Attribute, Dwarf_Sig8 *, Dwarf_Error *); int dwarf_formstring(Dwarf_Attribute, char **, Dwarf_Error *); int dwarf_formudata(Dwarf_Attribute, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_func_cu_offset(Dwarf_Func, Dwarf_Off *, Dwarf_Error *); int dwarf_func_die_offset(Dwarf_Func, Dwarf_Off *, Dwarf_Error *); int dwarf_func_name_offsets(Dwarf_Func, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_funcname(Dwarf_Func, char **, Dwarf_Error *); void dwarf_funcs_dealloc(Dwarf_Debug, Dwarf_Func *, Dwarf_Signed); int dwarf_get_ACCESS_name(unsigned, const char **); int dwarf_get_ATE_name(unsigned, const char **); int dwarf_get_AT_name(unsigned, const char **); int dwarf_get_CC_name(unsigned, const char **); int dwarf_get_CFA_name(unsigned, const char **); int dwarf_get_CHILDREN_name(unsigned, const char **); int dwarf_get_DSC_name(unsigned, const char **); int dwarf_get_DS_name(unsigned, const char **); int dwarf_get_EH_name(unsigned, const char **); int dwarf_get_END_name(unsigned, const char **); int dwarf_get_FORM_name(unsigned, const char **); int dwarf_get_ID_name(unsigned, const char **); int dwarf_get_INL_name(unsigned, const char **); int dwarf_get_LANG_name(unsigned, const char **); int dwarf_get_LNE_name(unsigned, const char **); int dwarf_get_LNS_name(unsigned, const char **); int dwarf_get_MACINFO_name(unsigned, const char **); int dwarf_get_OP_name(unsigned, const char **); int dwarf_get_ORD_name(unsigned, const char **); int dwarf_get_TAG_name(unsigned, const char **); int dwarf_get_VIRTUALITY_name(unsigned, const char **); int dwarf_get_VIS_name(unsigned, const char **); int dwarf_get_abbrev(Dwarf_Debug, Dwarf_Unsigned, Dwarf_Abbrev *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_abbrev_children_flag(Dwarf_Abbrev, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_abbrev_code(Dwarf_Abbrev, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_abbrev_entry(Dwarf_Abbrev, Dwarf_Signed, Dwarf_Half *, Dwarf_Signed *, Dwarf_Off *, Dwarf_Error *); int dwarf_get_abbrev_tag(Dwarf_Abbrev, Dwarf_Half *, Dwarf_Error *); int dwarf_get_address_size(Dwarf_Debug, Dwarf_Half *, Dwarf_Error *); int dwarf_get_arange(Dwarf_Arange *, Dwarf_Unsigned, Dwarf_Addr, Dwarf_Arange *, Dwarf_Error *); int dwarf_get_arange_cu_header_offset(Dwarf_Arange, Dwarf_Off *, Dwarf_Error *); int dwarf_get_arange_info(Dwarf_Arange, Dwarf_Addr *, Dwarf_Unsigned *, Dwarf_Off *, Dwarf_Error *); int dwarf_get_aranges(Dwarf_Debug, Dwarf_Arange **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_cie_index(Dwarf_Cie, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_cie_info(Dwarf_Cie, Dwarf_Unsigned *, Dwarf_Small *, char **, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_cie_of_fde(Dwarf_Fde, Dwarf_Cie *, Dwarf_Error *); int dwarf_get_cu_die_offset(Dwarf_Arange, Dwarf_Off *, Dwarf_Error *); int dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug, Dwarf_Off, Dwarf_Off *, Dwarf_Error *); int dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug, Dwarf_Off, Dwarf_Bool, Dwarf_Off *, Dwarf_Error *); Dwarf_Bool dwarf_get_die_infotypes_flag(Dwarf_Die); int dwarf_get_elf(Dwarf_Debug, Elf **, Dwarf_Error *); int dwarf_get_fde_at_pc(Dwarf_Fde *, Dwarf_Addr, Dwarf_Fde *, Dwarf_Addr *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_info_for_all_regs(Dwarf_Fde, Dwarf_Addr, Dwarf_Regtable *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_info_for_all_regs3(Dwarf_Fde, Dwarf_Addr, Dwarf_Regtable3 *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_info_for_cfa_reg3(Dwarf_Fde, Dwarf_Addr, Dwarf_Small *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Ptr *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_info_for_reg(Dwarf_Fde, Dwarf_Half, Dwarf_Addr, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_info_for_reg3(Dwarf_Fde, Dwarf_Half, Dwarf_Addr, Dwarf_Small *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Ptr *, Dwarf_Addr *, Dwarf_Error *); int dwarf_get_fde_instr_bytes(Dwarf_Fde, Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_fde_list(Dwarf_Debug, Dwarf_Cie **, Dwarf_Signed *, Dwarf_Fde **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_fde_list_eh(Dwarf_Debug, Dwarf_Cie **, Dwarf_Signed *, Dwarf_Fde **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_fde_n(Dwarf_Fde *, Dwarf_Unsigned, Dwarf_Fde *, Dwarf_Error *); int dwarf_get_fde_range(Dwarf_Fde, Dwarf_Addr *, Dwarf_Unsigned *, Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Off *, Dwarf_Signed *, Dwarf_Off *, Dwarf_Error *); enum Dwarf_Form_Class dwarf_get_form_class(Dwarf_Half, Dwarf_Half, Dwarf_Half, Dwarf_Half); int dwarf_get_funcs(Dwarf_Debug, Dwarf_Func **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_globals(Dwarf_Debug, Dwarf_Global **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_loclist_entry(Dwarf_Debug, Dwarf_Unsigned, Dwarf_Addr *, Dwarf_Addr *, Dwarf_Ptr *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_macro_details(Dwarf_Debug, Dwarf_Off, Dwarf_Unsigned, Dwarf_Signed *, Dwarf_Macro_Details **, Dwarf_Error *); int dwarf_get_pubtypes(Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_ranges(Dwarf_Debug, Dwarf_Off, Dwarf_Ranges **, Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_ranges_a(Dwarf_Debug, Dwarf_Off, Dwarf_Die, Dwarf_Ranges **, Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_relocation_info(Dwarf_P_Debug, Dwarf_Signed *, Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Relocation_Data *, Dwarf_Error *); int dwarf_get_relocation_info_count(Dwarf_P_Debug, Dwarf_Unsigned *, int *, Dwarf_Error *); Dwarf_Ptr dwarf_get_section_bytes(Dwarf_P_Debug, Dwarf_Signed, Dwarf_Signed *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_get_section_max_offsets(Dwarf_Debug, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *); int dwarf_get_section_max_offsets_b(Dwarf_Debug, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Unsigned *); int dwarf_get_str(Dwarf_Debug, Dwarf_Off, char **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_types(Dwarf_Debug, Dwarf_Type **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_vars(Dwarf_Debug, Dwarf_Var **, Dwarf_Signed *, Dwarf_Error *); int dwarf_get_weaks(Dwarf_Debug, Dwarf_Weak **, Dwarf_Signed *, Dwarf_Error *); int dwarf_global_cu_offset(Dwarf_Global, Dwarf_Off *, Dwarf_Error *); int dwarf_global_die_offset(Dwarf_Global, Dwarf_Off *, Dwarf_Error *); int dwarf_global_formref(Dwarf_Attribute, Dwarf_Off *, Dwarf_Error *); int dwarf_global_name_offsets(Dwarf_Global, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); void dwarf_globals_dealloc(Dwarf_Debug, Dwarf_Global *, Dwarf_Signed); int dwarf_globname(Dwarf_Global, char **, Dwarf_Error *); int dwarf_hasattr(Dwarf_Die, Dwarf_Half, Dwarf_Bool *, Dwarf_Error *); int dwarf_hasform(Dwarf_Attribute, Dwarf_Half, Dwarf_Bool *, Dwarf_Error *); int dwarf_highpc(Dwarf_Die, Dwarf_Addr *, Dwarf_Error *); int dwarf_highpc_b(Dwarf_Die, Dwarf_Addr *, Dwarf_Half *, enum Dwarf_Form_Class *, Dwarf_Error *); int dwarf_init(int, int, Dwarf_Handler, Dwarf_Ptr, Dwarf_Debug *, Dwarf_Error *); int dwarf_line_srcfileno(Dwarf_Line, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_lineaddr(Dwarf_Line, Dwarf_Addr *, Dwarf_Error *); int dwarf_linebeginstatement(Dwarf_Line, Dwarf_Bool *, Dwarf_Error *); int dwarf_lineblock(Dwarf_Line, Dwarf_Bool *, Dwarf_Error *); int dwarf_lineendsequence(Dwarf_Line, Dwarf_Bool *, Dwarf_Error *); int dwarf_lineno(Dwarf_Line, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_lineoff(Dwarf_Line, Dwarf_Signed *, Dwarf_Error *); int dwarf_linesrc(Dwarf_Line, char **, Dwarf_Error *); Dwarf_Unsigned dwarf_lne_end_sequence(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Error *); Dwarf_Unsigned dwarf_lne_set_address(Dwarf_P_Debug, Dwarf_Addr, Dwarf_Unsigned, Dwarf_Error *); int dwarf_loclist(Dwarf_Attribute, Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *); int dwarf_loclist_from_expr(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned, Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *); int dwarf_loclist_from_expr_a(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned, Dwarf_Half, Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *); int dwarf_loclist_from_expr_b(Dwarf_Debug, Dwarf_Ptr, Dwarf_Unsigned, Dwarf_Half, Dwarf_Half, Dwarf_Small, Dwarf_Locdesc **, Dwarf_Signed *, Dwarf_Error *); int dwarf_loclist_n(Dwarf_Attribute, Dwarf_Locdesc ***, Dwarf_Signed *, Dwarf_Error *); int dwarf_lowpc(Dwarf_Die, Dwarf_Addr *, Dwarf_Error *); Dwarf_P_Die dwarf_new_die(Dwarf_P_Debug, Dwarf_Tag, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_P_Die, Dwarf_Error *); Dwarf_P_Expr dwarf_new_expr(Dwarf_P_Debug, Dwarf_Error *); Dwarf_P_Fde dwarf_new_fde(Dwarf_P_Debug, Dwarf_Error *); int dwarf_next_cu_header(Dwarf_Debug, Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Off *, Dwarf_Half *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_next_cu_header_b(Dwarf_Debug, Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Off *, Dwarf_Half *, Dwarf_Half *, Dwarf_Half *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_next_cu_header_c(Dwarf_Debug, Dwarf_Bool, Dwarf_Unsigned *, Dwarf_Half *, Dwarf_Off *, Dwarf_Half *, Dwarf_Half *, Dwarf_Half *, Dwarf_Sig8 *, Dwarf_Unsigned *, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_next_types_section(Dwarf_Debug, Dwarf_Error *); int dwarf_object_finish(Dwarf_Debug, Dwarf_Error *); int dwarf_object_init(Dwarf_Obj_Access_Interface *, Dwarf_Handler, Dwarf_Ptr, Dwarf_Debug *, Dwarf_Error *); int dwarf_offdie(Dwarf_Debug, Dwarf_Off, Dwarf_Die *, Dwarf_Error *); int dwarf_offdie_b(Dwarf_Debug, Dwarf_Off, Dwarf_Bool, Dwarf_Die *, Dwarf_Error *); Dwarf_Unsigned dwarf_producer_finish(Dwarf_P_Debug, Dwarf_Error *); Dwarf_P_Debug dwarf_producer_init(Dwarf_Unsigned, Dwarf_Callback_Func, Dwarf_Handler, Dwarf_Ptr, Dwarf_Error *); Dwarf_P_Debug dwarf_producer_init_b(Dwarf_Unsigned, Dwarf_Callback_Func_b, Dwarf_Handler, Dwarf_Ptr, Dwarf_Error *); int dwarf_producer_set_isa(Dwarf_P_Debug, enum Dwarf_ISA, Dwarf_Error *); int dwarf_pubtype_cu_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *); int dwarf_pubtype_die_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *); int dwarf_pubtype_name_offsets(Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_pubtypename(Dwarf_Type, char **, Dwarf_Error *); void dwarf_pubtypes_dealloc(Dwarf_Debug, Dwarf_Type *, Dwarf_Signed); void dwarf_ranges_dealloc(Dwarf_Debug, Dwarf_Ranges *, Dwarf_Signed); void dwarf_reset_section_bytes(Dwarf_P_Debug); Dwarf_Half dwarf_set_frame_cfa_value(Dwarf_Debug, Dwarf_Half); Dwarf_Half dwarf_set_frame_rule_initial_value(Dwarf_Debug, Dwarf_Half); Dwarf_Half dwarf_set_frame_rule_table_size(Dwarf_Debug, Dwarf_Half); Dwarf_Half dwarf_set_frame_same_value(Dwarf_Debug, Dwarf_Half); Dwarf_Half dwarf_set_frame_undefined_value(Dwarf_Debug, Dwarf_Half); int dwarf_set_reloc_application(int); Dwarf_Ptr dwarf_seterrarg(Dwarf_Debug, Dwarf_Ptr); Dwarf_Handler dwarf_seterrhand(Dwarf_Debug, Dwarf_Handler); int dwarf_siblingof(Dwarf_Debug, Dwarf_Die, Dwarf_Die *, Dwarf_Error *); int dwarf_siblingof_b(Dwarf_Debug, Dwarf_Die, Dwarf_Die *, Dwarf_Bool, Dwarf_Error *); int dwarf_srcfiles(Dwarf_Die, char ***, Dwarf_Signed *, Dwarf_Error *); int dwarf_srclang(Dwarf_Die, Dwarf_Unsigned *, Dwarf_Error *); int dwarf_srclines(Dwarf_Die, Dwarf_Line **, Dwarf_Signed *, Dwarf_Error *); void dwarf_srclines_dealloc(Dwarf_Debug, Dwarf_Line *, Dwarf_Signed); int dwarf_start_macro_file(Dwarf_P_Debug, Dwarf_Unsigned, Dwarf_Unsigned, Dwarf_Error *); int dwarf_tag(Dwarf_Die, Dwarf_Half *, Dwarf_Error *); Dwarf_Signed dwarf_transform_to_disk_form(Dwarf_P_Debug, Dwarf_Error *); int dwarf_type_cu_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *); int dwarf_type_die_offset(Dwarf_Type, Dwarf_Off *, Dwarf_Error *); int dwarf_type_name_offsets(Dwarf_Type, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_typename(Dwarf_Type, char **, Dwarf_Error *); void dwarf_types_dealloc(Dwarf_Debug, Dwarf_Type *, Dwarf_Signed); int dwarf_undef_macro(Dwarf_P_Debug, Dwarf_Unsigned, char *, Dwarf_Error *); int dwarf_var_cu_offset(Dwarf_Var, Dwarf_Off *, Dwarf_Error *); int dwarf_var_die_offset(Dwarf_Var, Dwarf_Off *, Dwarf_Error *); int dwarf_var_name_offsets(Dwarf_Var, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_varname(Dwarf_Var, char **, Dwarf_Error *); void dwarf_vars_dealloc(Dwarf_Debug, Dwarf_Var *, Dwarf_Signed); int dwarf_vendor_ext(Dwarf_P_Debug, Dwarf_Unsigned, char *, Dwarf_Error *); int dwarf_weak_cu_offset(Dwarf_Weak, Dwarf_Off *, Dwarf_Error *); int dwarf_weak_die_offset(Dwarf_Weak, Dwarf_Off *, Dwarf_Error *); int dwarf_weak_name_offsets(Dwarf_Weak, char **, Dwarf_Off *, Dwarf_Off *, Dwarf_Error *); int dwarf_weakname(Dwarf_Weak, char **, Dwarf_Error *); void dwarf_weaks_dealloc(Dwarf_Debug, Dwarf_Weak *, Dwarf_Signed); int dwarf_whatattr(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *); int dwarf_whatform(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *); int dwarf_whatform_direct(Dwarf_Attribute, Dwarf_Half *, Dwarf_Error *); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* !_LIBDWARF_H_ */ Index: head/contrib/elftoolchain/libdwarf/libdwarf_lineno.c =================================================================== --- head/contrib/elftoolchain/libdwarf/libdwarf_lineno.c (revision 280931) +++ head/contrib/elftoolchain/libdwarf/libdwarf_lineno.c (revision 280932) @@ -1,775 +1,777 @@ /*- * Copyright (c) 2009,2010 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "_libdwarf.h" -ELFTC_VCSID("$Id: libdwarf_lineno.c 3100 2014-10-25 20:34:29Z jkoshy $"); +ELFTC_VCSID("$Id: libdwarf_lineno.c 3164 2015-02-19 01:20:12Z kaiwang27 $"); static int _dwarf_lineno_add_file(Dwarf_LineInfo li, uint8_t **p, const char *compdir, Dwarf_Error *error, Dwarf_Debug dbg) { Dwarf_LineFile lf; const char *dirname; uint8_t *src; int slen; src = *p; if ((lf = malloc(sizeof(struct _Dwarf_LineFile))) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } lf->lf_fullpath = NULL; lf->lf_fname = (char *) src; src += strlen(lf->lf_fname) + 1; lf->lf_dirndx = _dwarf_decode_uleb128(&src); if (lf->lf_dirndx > li->li_inclen) { free(lf); DWARF_SET_ERROR(dbg, error, DW_DLE_DIR_INDEX_BAD); return (DW_DLE_DIR_INDEX_BAD); } /* Make full pathname if need. */ if (*lf->lf_fname != '/') { dirname = compdir; if (lf->lf_dirndx > 0) dirname = li->li_incdirs[lf->lf_dirndx - 1]; if (dirname != NULL) { slen = strlen(dirname) + strlen(lf->lf_fname) + 2; if ((lf->lf_fullpath = malloc(slen)) == NULL) { free(lf); DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } snprintf(lf->lf_fullpath, slen, "%s/%s", dirname, lf->lf_fname); } } lf->lf_mtime = _dwarf_decode_uleb128(&src); lf->lf_size = _dwarf_decode_uleb128(&src); STAILQ_INSERT_TAIL(&li->li_lflist, lf, lf_next); li->li_lflen++; *p = src; return (DW_DLE_NONE); } static int _dwarf_lineno_run_program(Dwarf_CU cu, Dwarf_LineInfo li, uint8_t *p, uint8_t *pe, const char *compdir, Dwarf_Error *error) { Dwarf_Debug dbg; Dwarf_Line ln, tln; uint64_t address, file, line, column, opsize; int is_stmt, basic_block, end_sequence; int ret; #define RESET_REGISTERS \ do { \ address = 0; \ file = 1; \ line = 1; \ column = 0; \ is_stmt = li->li_defstmt; \ basic_block = 0; \ end_sequence = 0; \ } while(0) #define APPEND_ROW \ do { \ ln = malloc(sizeof(struct _Dwarf_Line)); \ if (ln == NULL) { \ ret = DW_DLE_MEMORY; \ DWARF_SET_ERROR(dbg, error, ret); \ goto prog_fail; \ } \ ln->ln_li = li; \ ln->ln_addr = address; \ ln->ln_symndx = 0; \ ln->ln_fileno = file; \ ln->ln_lineno = line; \ ln->ln_column = column; \ ln->ln_bblock = basic_block; \ ln->ln_stmt = is_stmt; \ ln->ln_endseq = end_sequence; \ STAILQ_INSERT_TAIL(&li->li_lnlist, ln, ln_next);\ li->li_lnlen++; \ } while(0) #define LINE(x) (li->li_lbase + (((x) - li->li_opbase) % li->li_lrange)) #define ADDRESS(x) ((((x) - li->li_opbase) / li->li_lrange) * li->li_minlen) dbg = cu->cu_dbg; /* * Set registers to their default values. */ RESET_REGISTERS; /* * Start line number program. */ while (p < pe) { if (*p == 0) { /* * Extended Opcodes. */ p++; opsize = _dwarf_decode_uleb128(&p); switch (*p) { case DW_LNE_end_sequence: p++; end_sequence = 1; APPEND_ROW; RESET_REGISTERS; break; case DW_LNE_set_address: p++; address = dbg->decode(&p, cu->cu_pointer_size); break; case DW_LNE_define_file: p++; ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg); if (ret != DW_DLE_NONE) goto prog_fail; break; default: /* Unrecognized extened opcodes. */ p += opsize; } } else if (*p > 0 && *p < li->li_opbase) { /* * Standard Opcodes. */ switch (*p++) { case DW_LNS_copy: APPEND_ROW; basic_block = 0; break; case DW_LNS_advance_pc: address += _dwarf_decode_uleb128(&p) * li->li_minlen; break; case DW_LNS_advance_line: line += _dwarf_decode_sleb128(&p); break; case DW_LNS_set_file: file = _dwarf_decode_uleb128(&p); break; case DW_LNS_set_column: column = _dwarf_decode_uleb128(&p); break; case DW_LNS_negate_stmt: is_stmt = !is_stmt; break; case DW_LNS_set_basic_block: basic_block = 1; break; case DW_LNS_const_add_pc: address += ADDRESS(255); break; case DW_LNS_fixed_advance_pc: address += dbg->decode(&p, 2); break; case DW_LNS_set_prologue_end: break; case DW_LNS_set_epilogue_begin: break; case DW_LNS_set_isa: (void) _dwarf_decode_uleb128(&p); break; default: /* Unrecognized extened opcodes. What to do? */ break; } } else { /* * Special Opcodes. */ line += LINE(*p); address += ADDRESS(*p); APPEND_ROW; basic_block = 0; p++; } } return (DW_DLE_NONE); prog_fail: STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); free(ln); } return (ret); #undef RESET_REGISTERS #undef APPEND_ROW #undef LINE #undef ADDRESS } int _dwarf_lineno_init(Dwarf_Die die, uint64_t offset, Dwarf_Error *error) { Dwarf_Debug dbg; Dwarf_Section *ds; Dwarf_CU cu; Dwarf_Attribute at; Dwarf_LineInfo li; Dwarf_LineFile lf, tlf; const char *compdir; uint64_t length, hdroff, endoff; uint8_t *p; int dwarf_size, i, ret; cu = die->die_cu; assert(cu != NULL); dbg = cu->cu_dbg; assert(dbg != NULL); if ((ds = _dwarf_find_section(dbg, ".debug_line")) == NULL) return (DW_DLE_NONE); /* * Try to find out the dir where the CU was compiled. Later we * will use the dir to create full pathnames, if need. */ compdir = NULL; at = _dwarf_attr_find(die, DW_AT_comp_dir); if (at != NULL) { switch (at->at_form) { case DW_FORM_strp: compdir = at->u[1].s; break; case DW_FORM_string: compdir = at->u[0].s; break; default: break; } } length = dbg->read(ds->ds_data, &offset, 4); if (length == 0xffffffff) { dwarf_size = 8; length = dbg->read(ds->ds_data, &offset, 8); } else dwarf_size = 4; if (length > ds->ds_size - offset) { DWARF_SET_ERROR(dbg, error, DW_DLE_DEBUG_LINE_LENGTH_BAD); return (DW_DLE_DEBUG_LINE_LENGTH_BAD); } if ((li = calloc(1, sizeof(struct _Dwarf_LineInfo))) == NULL) { DWARF_SET_ERROR(dbg, error, DW_DLE_MEMORY); return (DW_DLE_MEMORY); } /* * Read in line number program header. */ li->li_length = length; endoff = offset + length; li->li_version = dbg->read(ds->ds_data, &offset, 2); /* FIXME: verify version */ li->li_hdrlen = dbg->read(ds->ds_data, &offset, dwarf_size); hdroff = offset; li->li_minlen = dbg->read(ds->ds_data, &offset, 1); + if (li->li_version == 4) + li->li_maxop = dbg->read(ds->ds_data, &offset, 1); li->li_defstmt = dbg->read(ds->ds_data, &offset, 1); li->li_lbase = dbg->read(ds->ds_data, &offset, 1); li->li_lrange = dbg->read(ds->ds_data, &offset, 1); li->li_opbase = dbg->read(ds->ds_data, &offset, 1); STAILQ_INIT(&li->li_lflist); STAILQ_INIT(&li->li_lnlist); if ((int)li->li_hdrlen - 5 < li->li_opbase - 1) { ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } if ((li->li_oplen = malloc(li->li_opbase)) == NULL) { ret = DW_DLE_MEMORY; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } /* * Read in std opcode arg length list. Note that the first * element is not used. */ for (i = 1; i < li->li_opbase; i++) li->li_oplen[i] = dbg->read(ds->ds_data, &offset, 1); /* * Check how many strings in the include dir string array. */ length = 0; p = ds->ds_data + offset; while (*p != '\0') { while (*p++ != '\0') ; length++; } li->li_inclen = length; /* Sanity check. */ if (p - ds->ds_data > (int) ds->ds_size) { ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } if (length != 0) { if ((li->li_incdirs = malloc(length * sizeof(char *))) == NULL) { ret = DW_DLE_MEMORY; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } } /* Fill in include dir array. */ i = 0; p = ds->ds_data + offset; while (*p != '\0') { li->li_incdirs[i++] = (char *) p; while (*p++ != '\0') ; } p++; /* * Process file list. */ while (*p != '\0') { ret = _dwarf_lineno_add_file(li, &p, compdir, error, dbg); if (ret != DW_DLE_NONE) goto fail_cleanup; if (p - ds->ds_data > (int) ds->ds_size) { ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } } p++; /* Sanity check. */ if (p - ds->ds_data - hdroff != li->li_hdrlen) { ret = DW_DLE_DEBUG_LINE_LENGTH_BAD; DWARF_SET_ERROR(dbg, error, ret); goto fail_cleanup; } /* * Process line number program. */ ret = _dwarf_lineno_run_program(cu, li, p, ds->ds_data + endoff, compdir, error); if (ret != DW_DLE_NONE) goto fail_cleanup; cu->cu_lineinfo = li; return (DW_DLE_NONE); fail_cleanup: STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); if (lf->lf_fullpath) free(lf->lf_fullpath); free(lf); } if (li->li_oplen) free(li->li_oplen); if (li->li_incdirs) free(li->li_incdirs); free(li); return (ret); } void _dwarf_lineno_cleanup(Dwarf_LineInfo li) { Dwarf_LineFile lf, tlf; Dwarf_Line ln, tln; if (li == NULL) return; STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); if (lf->lf_fullpath) free(lf->lf_fullpath); free(lf); } STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); free(ln); } if (li->li_oplen) free(li->li_oplen); if (li->li_incdirs) free(li->li_incdirs); if (li->li_lnarray) free(li->li_lnarray); if (li->li_lfnarray) free(li->li_lfnarray); free(li); } static int _dwarf_lineno_gen_program(Dwarf_P_Debug dbg, Dwarf_P_Section ds, Dwarf_Rel_Section drs, Dwarf_Error * error) { Dwarf_LineInfo li; Dwarf_Line ln; Dwarf_Unsigned address, file, line, spc; Dwarf_Unsigned addr0, maddr; Dwarf_Signed line0, column; int is_stmt, basic_block; int need_copy; int ret; #define RESET_REGISTERS \ do { \ address = 0; \ file = 1; \ line = 1; \ column = 0; \ is_stmt = li->li_defstmt; \ basic_block = 0; \ } while(0) li = dbg->dbgp_lineinfo; maddr = (255 - li->li_opbase) / li->li_lrange; RESET_REGISTERS; STAILQ_FOREACH(ln, &li->li_lnlist, ln_next) { if (ln->ln_symndx > 0) { /* * Generate DW_LNE_set_address extended op. */ RCHECK(WRITE_VALUE(0, 1)); RCHECK(WRITE_ULEB128(dbg->dbg_pointer_size + 1)); RCHECK(WRITE_VALUE(DW_LNE_set_address, 1)); RCHECK(_dwarf_reloc_entry_add(dbg, drs, ds, dwarf_drt_data_reloc, dbg->dbg_pointer_size, ds->ds_size, ln->ln_symndx, ln->ln_addr, NULL, error)); address = ln->ln_addr; continue; } else if (ln->ln_endseq) { addr0 = (ln->ln_addr - address) / li->li_minlen; if (addr0 != 0) { RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); RCHECK(WRITE_ULEB128(addr0)); } /* * Generate DW_LNE_end_sequence. */ RCHECK(WRITE_VALUE(0, 1)); RCHECK(WRITE_ULEB128(1)); RCHECK(WRITE_VALUE(DW_LNE_end_sequence, 1)); RESET_REGISTERS; continue; } /* * Generate standard opcodes for file, column, is_stmt or * basic_block changes. */ if (ln->ln_fileno != file) { RCHECK(WRITE_VALUE(DW_LNS_set_file, 1)); RCHECK(WRITE_ULEB128(ln->ln_fileno)); file = ln->ln_fileno; } if (ln->ln_column != column) { RCHECK(WRITE_VALUE(DW_LNS_set_column, 1)); RCHECK(WRITE_ULEB128(ln->ln_column)); column = ln->ln_column; } if (ln->ln_stmt != is_stmt) { RCHECK(WRITE_VALUE(DW_LNS_negate_stmt, 1)); is_stmt = ln->ln_stmt; } if (ln->ln_bblock && !basic_block) { RCHECK(WRITE_VALUE(DW_LNS_set_basic_block, 1)); basic_block = 1; } /* * Calculate address and line number change. */ addr0 = (ln->ln_addr - address) / li->li_minlen; line0 = ln->ln_lineno - line; if (addr0 == 0 && line0 == 0) continue; /* * Check if line delta is with the range and if the special * opcode can be used. */ assert(li->li_lbase <= 0); if (line0 >= li->li_lbase && line0 <= li->li_lbase + li->li_lrange - 1) { spc = (line0 - li->li_lbase) + (li->li_lrange * addr0) + li->li_opbase; if (spc <= 255) { RCHECK(WRITE_VALUE(spc, 1)); basic_block = 0; goto next_line; } } /* Generate DW_LNS_advance_line for line number change. */ if (line0 != 0) { RCHECK(WRITE_VALUE(DW_LNS_advance_line, 1)); RCHECK(WRITE_SLEB128(line0)); line0 = 0; need_copy = 1; } else need_copy = basic_block; if (addr0 != 0) { /* See if it can be handled by DW_LNS_const_add_pc. */ spc = (line0 - li->li_lbase) + (li->li_lrange * (addr0 - maddr)) + li->li_opbase; if (addr0 >= maddr && spc <= 255) { RCHECK(WRITE_VALUE(DW_LNS_const_add_pc, 1)); RCHECK(WRITE_VALUE(spc, 1)); } else { /* Otherwise we use DW_LNS_advance_pc. */ RCHECK(WRITE_VALUE(DW_LNS_advance_pc, 1)); RCHECK(WRITE_ULEB128(addr0)); } } if (need_copy) { RCHECK(WRITE_VALUE(DW_LNS_copy, 1)); basic_block = 0; } next_line: address = ln->ln_addr; line = ln->ln_lineno; } return (DW_DLE_NONE); gen_fail: return (ret); #undef RESET_REGISTERS } static uint8_t _dwarf_get_minlen(Dwarf_P_Debug dbg) { assert(dbg != NULL); switch (dbg->dbgp_isa) { case DW_ISA_ARM: return (2); case DW_ISA_X86: case DW_ISA_X86_64: return (1); default: return (4); } } static uint8_t oplen[] = {0, 1, 1, 1, 1, 0, 0, 0, 1}; int _dwarf_lineno_gen(Dwarf_P_Debug dbg, Dwarf_Error *error) { Dwarf_LineInfo li; Dwarf_LineFile lf; Dwarf_P_Section ds; Dwarf_Rel_Section drs; Dwarf_Unsigned offset; int i, ret; assert(dbg != NULL && dbg->dbgp_lineinfo != NULL); li = dbg->dbgp_lineinfo; if (STAILQ_EMPTY(&li->li_lnlist)) return (DW_DLE_NONE); li->li_length = 0; li->li_version = 2; li->li_hdrlen = 0; li->li_minlen = _dwarf_get_minlen(dbg); li->li_defstmt = 1; li->li_lbase = -5; li->li_lrange = 14; li->li_opbase = 10; /* Create .debug_line section. */ if ((ret = _dwarf_section_init(dbg, &ds, ".debug_line", 0, error)) != DW_DLE_NONE) return (ret); /* Create relocation section for .debug_line */ if ((ret = _dwarf_reloc_section_init(dbg, &drs, ds, error)) != DW_DLE_NONE) goto gen_fail1; /* Length placeholder. (We only use 32-bit DWARF format) */ RCHECK(WRITE_VALUE(0, 4)); /* Write line number dwarf version. (DWARF2) */ RCHECK(WRITE_VALUE(li->li_version, 2)); /* Header length placeholder. */ offset = ds->ds_size; RCHECK(WRITE_VALUE(li->li_hdrlen, 4)); /* Write minimum instruction length. */ RCHECK(WRITE_VALUE(li->li_minlen, 1)); /* * Write initial value for is_stmt. XXX Which default value we * should use? */ RCHECK(WRITE_VALUE(li->li_defstmt, 1)); /* * Write line_base and line_range. FIXME These value needs to be * fine tuned. */ RCHECK(WRITE_VALUE(li->li_lbase, 1)); RCHECK(WRITE_VALUE(li->li_lrange, 1)); /* Write opcode_base. (DWARF2) */ RCHECK(WRITE_VALUE(li->li_opbase, 1)); /* Write standard op length array. */ RCHECK(WRITE_BLOCK(oplen, sizeof(oplen) / sizeof(oplen[0]))); /* Write the list of include directories. */ for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) RCHECK(WRITE_STRING(li->li_incdirs[i])); RCHECK(WRITE_VALUE(0, 1)); /* Write the list of filenames. */ STAILQ_FOREACH(lf, &li->li_lflist, lf_next) { RCHECK(WRITE_STRING(lf->lf_fname)); RCHECK(WRITE_ULEB128(lf->lf_dirndx)); RCHECK(WRITE_ULEB128(lf->lf_mtime)); RCHECK(WRITE_ULEB128(lf->lf_size)); } RCHECK(WRITE_VALUE(0, 1)); /* Fill in the header length. */ li->li_hdrlen = ds->ds_size - offset - 4; dbg->write(ds->ds_data, &offset, li->li_hdrlen, 4); /* Generate the line number program. */ RCHECK(_dwarf_lineno_gen_program(dbg, ds, drs, error)); /* Fill in the length of this line info. */ li->li_length = ds->ds_size - 4; offset = 0; dbg->write(ds->ds_data, &offset, li->li_length, 4); /* Notify the creation of .debug_line ELF section. */ RCHECK(_dwarf_section_callback(dbg, ds, SHT_PROGBITS, 0, 0, 0, error)); /* Finalize relocation section for .debug_line. */ RCHECK(_dwarf_reloc_section_finalize(dbg, drs, error)); return (DW_DLE_NONE); gen_fail: _dwarf_reloc_section_free(dbg, &drs); gen_fail1: _dwarf_section_free(dbg, &ds); return (ret); } void _dwarf_lineno_pro_cleanup(Dwarf_P_Debug dbg) { Dwarf_LineInfo li; Dwarf_LineFile lf, tlf; Dwarf_Line ln, tln; int i; assert(dbg != NULL && dbg->dbg_mode == DW_DLC_WRITE); if (dbg->dbgp_lineinfo == NULL) return; li = dbg->dbgp_lineinfo; STAILQ_FOREACH_SAFE(lf, &li->li_lflist, lf_next, tlf) { STAILQ_REMOVE(&li->li_lflist, lf, _Dwarf_LineFile, lf_next); if (lf->lf_fname) free(lf->lf_fname); free(lf); } STAILQ_FOREACH_SAFE(ln, &li->li_lnlist, ln_next, tln) { STAILQ_REMOVE(&li->li_lnlist, ln, _Dwarf_Line, ln_next); free(ln); } if (li->li_incdirs) { for (i = 0; (Dwarf_Unsigned) i < li->li_inclen; i++) free(li->li_incdirs[i]); free(li->li_incdirs); } free(li); dbg->dbgp_lineinfo = NULL; } Index: head/contrib/elftoolchain/libelf/_libelf.h =================================================================== --- head/contrib/elftoolchain/libelf/_libelf.h (revision 280931) +++ head/contrib/elftoolchain/libelf/_libelf.h (revision 280932) @@ -1,235 +1,239 @@ /*- * Copyright (c) 2006,2008-2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libelf.h 3011 2014-03-23 03:32:42Z jkoshy $ + * $Id: _libelf.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef __LIBELF_H_ #define __LIBELF_H_ #include #include "_libelf_config.h" #include "_elftc.h" /* * Library-private data structures. */ #define LIBELF_MSG_SIZE 256 struct _libelf_globals { int libelf_arch; unsigned int libelf_byteorder; int libelf_class; int libelf_error; int libelf_fillchar; unsigned int libelf_version; unsigned char libelf_msg[LIBELF_MSG_SIZE]; }; extern struct _libelf_globals _libelf; #define LIBELF_PRIVATE(N) (_libelf.libelf_##N) #define LIBELF_ELF_ERROR_MASK 0xFF #define LIBELF_OS_ERROR_SHIFT 8 #define LIBELF_ERROR(E, O) (((E) & LIBELF_ELF_ERROR_MASK) | \ ((O) << LIBELF_OS_ERROR_SHIFT)) #define LIBELF_SET_ERROR(E, O) do { \ LIBELF_PRIVATE(error) = LIBELF_ERROR(ELF_E_##E, (O)); \ } while (0) #define LIBELF_ADJUST_AR_SIZE(S) (((S) + 1U) & ~1U) /* * Flags for library internal use. These use the upper 16 bits of the * `e_flags' field. */ #define LIBELF_F_API_MASK 0x00FFFFU /* Flags defined by the API. */ #define LIBELF_F_AR_HEADER 0x010000U /* translated header available */ #define LIBELF_F_AR_VARIANT_SVR4 0x020000U /* BSD style ar(1) archive */ #define LIBELF_F_DATA_MALLOCED 0x040000U /* whether data was malloc'ed */ #define LIBELF_F_RAWFILE_MALLOC 0x080000U /* whether e_rawfile was malloc'ed */ #define LIBELF_F_RAWFILE_MMAP 0x100000U /* whether e_rawfile was mmap'ed */ #define LIBELF_F_SHDRS_LOADED 0x200000U /* whether all shdrs were read in */ #define LIBELF_F_SPECIAL_FILE 0x400000U /* non-regular file */ struct _Elf { int e_activations; /* activation count */ unsigned int e_byteorder; /* ELFDATA* */ int e_class; /* ELFCLASS* */ Elf_Cmd e_cmd; /* ELF_C_* used at creation time */ int e_fd; /* associated file descriptor */ unsigned int e_flags; /* ELF_F_* & LIBELF_F_* flags */ Elf_Kind e_kind; /* ELF_K_* */ Elf *e_parent; /* non-NULL for archive members */ unsigned char *e_rawfile; /* uninterpreted bytes */ size_t e_rawsize; /* size of uninterpreted bytes */ unsigned int e_version; /* file version */ /* * Header information for archive members. See the * LIBELF_F_AR_HEADER flag. */ union { Elf_Arhdr *e_arhdr; /* translated header */ unsigned char *e_rawhdr; /* untranslated header */ } e_hdr; union { struct { /* ar(1) archives */ off_t e_next; /* set by elf_rand()/elf_next() */ int e_nchildren; unsigned char *e_rawstrtab; /* file name strings */ size_t e_rawstrtabsz; unsigned char *e_rawsymtab; /* symbol table */ size_t e_rawsymtabsz; Elf_Arsym *e_symtab; size_t e_symtabsz; } e_ar; struct { /* regular ELF files */ union { Elf32_Ehdr *e_ehdr32; Elf64_Ehdr *e_ehdr64; } e_ehdr; union { Elf32_Phdr *e_phdr32; Elf64_Phdr *e_phdr64; } e_phdr; STAILQ_HEAD(, _Elf_Scn) e_scn; /* section list */ size_t e_nphdr; /* number of Phdr entries */ size_t e_nscn; /* number of sections */ size_t e_strndx; /* string table section index */ } e_elf; } e_u; }; /* * The internal descriptor wrapping the "Elf_Data" type. */ struct _Libelf_Data { Elf_Data d_data; /* The exported descriptor. */ Elf_Scn *d_scn; /* The containing section */ unsigned int d_flags; STAILQ_ENTRY(_Libelf_Data) d_next; }; struct _Elf_Scn { union { Elf32_Shdr s_shdr32; Elf64_Shdr s_shdr64; } s_shdr; STAILQ_HEAD(, _Libelf_Data) s_data; /* translated data */ STAILQ_HEAD(, _Libelf_Data) s_rawdata; /* raw data */ STAILQ_ENTRY(_Elf_Scn) s_next; struct _Elf *s_elf; /* parent ELF descriptor */ unsigned int s_flags; /* flags for the section as a whole */ size_t s_ndx; /* index# for this section */ uint64_t s_offset; /* managed by elf_update() */ uint64_t s_rawoff; /* original offset in the file */ uint64_t s_size; /* managed by elf_update() */ }; enum { ELF_TOFILE, ELF_TOMEMORY }; /* * The LIBELF_COPY macros are used to copy fields from a GElf_* * structure to their 32-bit counterparts, while checking for out of * range values. * * - LIBELF_COPY_U32 :: copy an unsigned 32 bit field. * - LIBELF_COPY_S32 :: copy a signed 32 bit field. */ #define LIBELF_COPY_U32(DST, SRC, NAME) do { \ if ((SRC)->NAME > UINT32_MAX) { \ LIBELF_SET_ERROR(RANGE, 0); \ return (0); \ } \ (DST)->NAME = (SRC)->NAME & 0xFFFFFFFFU; \ } while (0) #define LIBELF_COPY_S32(DST, SRC, NAME) do { \ if ((SRC)->NAME > INT32_MAX || \ (SRC)->NAME < INT32_MIN) { \ LIBELF_SET_ERROR(RANGE, 0); \ return (0); \ } \ (DST)->NAME = (int32_t) (SRC)->NAME; \ } while (0) /* * Function Prototypes. */ -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif struct _Libelf_Data *_libelf_allocate_data(Elf_Scn *_s); Elf *_libelf_allocate_elf(void); Elf_Scn *_libelf_allocate_scn(Elf *_e, size_t _ndx); Elf_Arhdr *_libelf_ar_gethdr(Elf *_e); Elf *_libelf_ar_open(Elf *_e, int _reporterror); Elf *_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar); Elf_Arsym *_libelf_ar_process_bsd_symtab(Elf *_ar, size_t *_dst); Elf_Arsym *_libelf_ar_process_svr4_symtab(Elf *_ar, size_t *_dst); long _libelf_checksum(Elf *_e, int _elfclass); void *_libelf_ehdr(Elf *_e, int _elfclass, int _allocate); unsigned int _libelf_falign(Elf_Type _t, int _elfclass); size_t _libelf_fsize(Elf_Type _t, int _elfclass, unsigned int _version, size_t count); int (*_libelf_get_translator(Elf_Type _t, int _direction, int _elfclass)) (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt, int _byteswap); void *_libelf_getphdr(Elf *_e, int _elfclass); void *_libelf_getshdr(Elf_Scn *_scn, int _elfclass); void _libelf_init_elf(Elf *_e, Elf_Kind _kind); int _libelf_load_section_headers(Elf *e, void *ehdr); unsigned int _libelf_malign(Elf_Type _t, int _elfclass); Elf *_libelf_memory(unsigned char *_image, size_t _sz, int _reporterror); size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version); void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count); Elf *_libelf_open_object(int _fd, Elf_Cmd _c, int _reporterror); struct _Libelf_Data *_libelf_release_data(struct _Libelf_Data *_d); Elf *_libelf_release_elf(Elf *_e); Elf_Scn *_libelf_release_scn(Elf_Scn *_s); int _libelf_setphnum(Elf *_e, void *_eh, int _elfclass, size_t _phnum); int _libelf_setshnum(Elf *_e, void *_eh, int _elfclass, size_t _shnum); int _libelf_setshstrndx(Elf *_e, void *_eh, int _elfclass, size_t _shstrndx); Elf_Data *_libelf_xlate(Elf_Data *_d, const Elf_Data *_s, unsigned int _encoding, int _elfclass, int _direction); int _libelf_xlate_shtype(uint32_t _sht); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* __LIBELF_H_ */ Index: head/contrib/elftoolchain/libelf/_libelf_config.h =================================================================== --- head/contrib/elftoolchain/libelf/_libelf_config.h (revision 280931) +++ head/contrib/elftoolchain/libelf/_libelf_config.h (revision 280932) @@ -1,183 +1,183 @@ /*- * Copyright (c) 2008-2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: _libelf_config.h 3143 2015-02-15 17:57:38Z emaste $ + * $Id: _libelf_config.h 3168 2015-02-24 19:17:47Z emaste $ */ -#ifdef __DragonFly__ +#if defined(__APPLE__) || defined(__DragonFly__) #if defined(__amd64__) #define LIBELF_ARCH EM_X86_64 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS64 #elif defined(__i386__) #define LIBELF_ARCH EM_386 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS32 #endif #endif /* __DragonFly__ */ #ifdef __FreeBSD__ /* * Define LIBELF_{ARCH,BYTEORDER,CLASS} based on the machine architecture. * See also: . */ #if defined(__amd64__) #define LIBELF_ARCH EM_X86_64 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS64 #elif defined(__aarch64__) #define LIBELF_ARCH EM_AARCH64 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS64 #elif defined(__arm__) #define LIBELF_ARCH EM_ARM #if defined(__ARMEB__) /* Big-endian ARM. */ #define LIBELF_BYTEORDER ELFDATA2MSB #else #define LIBELF_BYTEORDER ELFDATA2LSB #endif #define LIBELF_CLASS ELFCLASS32 #elif defined(__i386__) #define LIBELF_ARCH EM_386 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS32 #elif defined(__ia64__) #define LIBELF_ARCH EM_IA_64 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS64 #elif defined(__mips__) #define LIBELF_ARCH EM_MIPS #if defined(__MIPSEB__) #define LIBELF_BYTEORDER ELFDATA2MSB #else #define LIBELF_BYTEORDER ELFDATA2LSB #endif #define LIBELF_CLASS ELFCLASS32 #elif defined(__powerpc__) #define LIBELF_ARCH EM_PPC #define LIBELF_BYTEORDER ELFDATA2MSB #define LIBELF_CLASS ELFCLASS32 #elif defined(__sparc__) #define LIBELF_ARCH EM_SPARCV9 #define LIBELF_BYTEORDER ELFDATA2MSB #define LIBELF_CLASS ELFCLASS64 #else #error Unknown FreeBSD architecture. #endif #endif /* __FreeBSD__ */ /* * Definitions for Minix3. */ #ifdef __minix #define LIBELF_ARCH EM_386 #define LIBELF_BYTEORDER ELFDATA2LSB #define LIBELF_CLASS ELFCLASS32 #endif /* __minix */ #ifdef __NetBSD__ #include #if !defined(ARCH_ELFSIZE) #error ARCH_ELFSIZE is not defined. #endif #if ARCH_ELFSIZE == 32 #define LIBELF_ARCH ELF32_MACHDEP_ID #define LIBELF_BYTEORDER ELF32_MACHDEP_ENDIANNESS #define LIBELF_CLASS ELFCLASS32 #define Elf_Note Elf32_Nhdr #else #define LIBELF_ARCH ELF64_MACHDEP_ID #define LIBELF_BYTEORDER ELF64_MACHDEP_ENDIANNESS #define LIBELF_CLASS ELFCLASS64 #define Elf_Note Elf64_Nhdr #endif #endif /* __NetBSD__ */ #if defined(__OpenBSD__) #include #define LIBELF_ARCH ELF_TARG_MACH #define LIBELF_BYTEORDER ELF_TARG_DATA #define LIBELF_CLASS ELF_TARG_CLASS #endif /* * GNU & Linux compatibility. * * `__linux__' is defined in an environment runs the Linux kernel and glibc. * `__GNU__' is defined in an environment runs a GNU kernel (Hurd) and glibc. * `__GLIBC__' is defined for an environment that runs glibc over a non-GNU * kernel such as GNU/kFreeBSD. */ #if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) #if defined(__linux__) #include "native-elf-format.h" #define LIBELF_CLASS ELFTC_CLASS #define LIBELF_ARCH ELFTC_ARCH #define LIBELF_BYTEORDER ELFTC_BYTEORDER #endif /* defined(__linux__) */ #if LIBELF_CLASS == ELFCLASS32 #define Elf_Note Elf32_Nhdr #elif LIBELF_CLASS == ELFCLASS64 #define Elf_Note Elf64_Nhdr #else #error LIBELF_CLASS needs to be one of ELFCLASS32 or ELFCLASS64 #endif #endif /* defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) */ Index: head/contrib/elftoolchain/libelf/elf_data.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_data.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_data.c (revision 280932) @@ -1,270 +1,270 @@ /*- * Copyright (c) 2006,2008,2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_data.c 3009 2014-03-23 01:49:59Z jkoshy $"); +ELFTC_VCSID("$Id: elf_data.c 3177 2015-03-30 18:19:41Z emaste $"); Elf_Data * elf_getdata(Elf_Scn *s, Elf_Data *ed) { Elf *e; unsigned int sh_type; int elfclass, elftype; size_t count, fsz, msz; struct _Libelf_Data *d; uint64_t sh_align, sh_offset, sh_size; int (*xlate)(unsigned char *_d, size_t _dsz, unsigned char *_s, size_t _c, int _swap); d = (struct _Libelf_Data *) ed; if (s == NULL || (e = s->s_elf) == NULL || (d != NULL && s != d->d_scn)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert(e->e_kind == ELF_K_ELF); if (d == NULL && (d = STAILQ_FIRST(&s->s_data)) != NULL) return (&d->d_data); if (d != NULL) return (&STAILQ_NEXT(d, d_next)->d_data); if (e->e_rawfile == NULL) { /* * In the ELF_C_WRITE case, there is no source that * can provide data for the section. */ LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } elfclass = e->e_class; assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); if (elfclass == ELFCLASS32) { sh_type = s->s_shdr.s_shdr32.sh_type; sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; } else { sh_type = s->s_shdr.s_shdr64.sh_type; sh_offset = s->s_shdr.s_shdr64.sh_offset; sh_size = s->s_shdr.s_shdr64.sh_size; sh_align = s->s_shdr.s_shdr64.sh_addralign; } if (sh_type == SHT_NULL) { LIBELF_SET_ERROR(SECTION, 0); return (NULL); } if ((elftype = _libelf_xlate_shtype(sh_type)) < ELF_T_FIRST || elftype > ELF_T_LAST || (sh_type != SHT_NOBITS && sh_offset + sh_size > (uint64_t) e->e_rawsize)) { LIBELF_SET_ERROR(SECTION, 0); return (NULL); } if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) (elftype, (size_t) 1, e->e_version)) == 0) { LIBELF_SET_ERROR(UNIMPL, 0); return (NULL); } if (sh_size % fsz) { LIBELF_SET_ERROR(SECTION, 0); return (NULL); } if (sh_size / fsz > SIZE_MAX) { LIBELF_SET_ERROR(RANGE, 0); return (NULL); } count = (size_t) (sh_size / fsz); msz = _libelf_msize(elftype, elfclass, e->e_version); if (count > 0 && msz > SIZE_MAX / count) { LIBELF_SET_ERROR(RANGE, 0); return (NULL); } assert(msz > 0); assert(count <= SIZE_MAX); assert(msz * count <= SIZE_MAX); if ((d = _libelf_allocate_data(s)) == NULL) return (NULL); d->d_data.d_buf = NULL; d->d_data.d_off = 0; d->d_data.d_align = sh_align; d->d_data.d_size = msz * count; d->d_data.d_type = elftype; d->d_data.d_version = e->e_version; if (sh_type == SHT_NOBITS || sh_size == 0) { STAILQ_INSERT_TAIL(&s->s_data, d, d_next); return (&d->d_data); } if ((d->d_data.d_buf = malloc(msz * count)) == NULL) { (void) _libelf_release_data(d); LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } d->d_flags |= LIBELF_F_DATA_MALLOCED; xlate = _libelf_get_translator(elftype, ELF_TOMEMORY, elfclass); if (!(*xlate)(d->d_data.d_buf, (size_t) d->d_data.d_size, e->e_rawfile + sh_offset, count, e->e_byteorder != LIBELF_PRIVATE(byteorder))) { _libelf_release_data(d); LIBELF_SET_ERROR(DATA, 0); return (NULL); } STAILQ_INSERT_TAIL(&s->s_data, d, d_next); return (&d->d_data); } Elf_Data * elf_newdata(Elf_Scn *s) { Elf *e; struct _Libelf_Data *d; if (s == NULL || (e = s->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert(e->e_kind == ELF_K_ELF); /* * elf_newdata() has to append a data descriptor, so * bring in existing section data if not already present. */ if (e->e_rawfile && s->s_size > 0 && STAILQ_EMPTY(&s->s_data)) if (elf_getdata(s, NULL) == NULL) return (NULL); if ((d = _libelf_allocate_data(s)) == NULL) return (NULL); STAILQ_INSERT_TAIL(&s->s_data, d, d_next); d->d_data.d_align = 1; d->d_data.d_buf = NULL; d->d_data.d_off = (uint64_t) ~0; d->d_data.d_size = 0; d->d_data.d_type = ELF_T_BYTE; d->d_data.d_version = LIBELF_PRIVATE(version); (void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY); return (&d->d_data); } /* * Retrieve a data descriptor for raw (untranslated) data for section * `s'. */ Elf_Data * elf_rawdata(Elf_Scn *s, Elf_Data *ed) { Elf *e; int elf_class; uint32_t sh_type; struct _Libelf_Data *d; uint64_t sh_align, sh_offset, sh_size; if (s == NULL || (e = s->s_elf) == NULL || e->e_rawfile == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert(e->e_kind == ELF_K_ELF); d = (struct _Libelf_Data *) ed; if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL) return (&d->d_data); if (d != NULL) return (&STAILQ_NEXT(d, d_next)->d_data); elf_class = e->e_class; assert(elf_class == ELFCLASS32 || elf_class == ELFCLASS64); if (elf_class == ELFCLASS32) { sh_type = s->s_shdr.s_shdr32.sh_type; sh_offset = (uint64_t) s->s_shdr.s_shdr32.sh_offset; sh_size = (uint64_t) s->s_shdr.s_shdr32.sh_size; sh_align = (uint64_t) s->s_shdr.s_shdr32.sh_addralign; } else { sh_type = s->s_shdr.s_shdr64.sh_type; sh_offset = s->s_shdr.s_shdr64.sh_offset; sh_size = s->s_shdr.s_shdr64.sh_size; sh_align = s->s_shdr.s_shdr64.sh_addralign; } if (sh_type == SHT_NULL) { LIBELF_SET_ERROR(SECTION, 0); return (NULL); } if ((d = _libelf_allocate_data(s)) == NULL) return (NULL); d->d_data.d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL : e->e_rawfile + sh_offset; d->d_data.d_off = 0; d->d_data.d_align = sh_align; d->d_data.d_size = sh_size; d->d_data.d_type = ELF_T_BYTE; d->d_data.d_version = e->e_version; STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next); return (&d->d_data); } Index: head/contrib/elftoolchain/libelf/elf_end.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_end.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_end.c (revision 280932) @@ -1,97 +1,95 @@ /*- * Copyright (c) 2006,2008-2009,2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" #if ELFTC_HAVE_MMAP #include #endif -ELFTC_VCSID("$Id: elf_end.c 2240 2011-11-28 06:36:48Z jkoshy $"); +ELFTC_VCSID("$Id: elf_end.c 3174 2015-03-27 17:13:41Z emaste $"); int elf_end(Elf *e) { Elf *sv; Elf_Scn *scn, *tscn; if (e == NULL || e->e_activations == 0) return (0); if (--e->e_activations > 0) return (e->e_activations); assert(e->e_activations == 0); while (e && e->e_activations == 0) { switch (e->e_kind) { case ELF_K_AR: /* * If we still have open child descriptors, we * need to defer reclaiming resources till all * the child descriptors for the archive are * closed. */ if (e->e_u.e_ar.e_nchildren > 0) return (0); break; case ELF_K_ELF: /* * Reclaim all section descriptors. */ STAILQ_FOREACH_SAFE(scn, &e->e_u.e_elf.e_scn, s_next, tscn) scn = _libelf_release_scn(scn); break; case ELF_K_NUM: assert(0); default: break; } if (e->e_rawfile) { if (e->e_flags & LIBELF_F_RAWFILE_MALLOC) free(e->e_rawfile); #if ELFTC_HAVE_MMAP else if (e->e_flags & LIBELF_F_RAWFILE_MMAP) (void) munmap(e->e_rawfile, e->e_rawsize); #endif } sv = e; if ((e = e->e_parent) != NULL) e->e_u.e_ar.e_nchildren--; sv = _libelf_release_elf(sv); } return (0); } Index: head/contrib/elftoolchain/libelf/elf_errmsg.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_errmsg.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_errmsg.c (revision 280932) @@ -1,85 +1,83 @@ /*- * Copyright (c) 2006,2008,2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_errmsg.c 3012 2014-03-23 03:41:38Z jkoshy $"); +ELFTC_VCSID("$Id: elf_errmsg.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Retrieve a human readable translation for an error message. */ static const char *_libelf_errors[] = { #define DEFINE_ERROR(N,S) [ELF_E_##N] = S DEFINE_ERROR(NONE, "No Error"), DEFINE_ERROR(ARCHIVE, "Malformed ar(1) archive"), DEFINE_ERROR(ARGUMENT, "Invalid argument"), DEFINE_ERROR(CLASS, "ELF class mismatch"), DEFINE_ERROR(DATA, "Invalid data buffer descriptor"), DEFINE_ERROR(HEADER, "Missing or malformed ELF header"), DEFINE_ERROR(IO, "I/O error"), DEFINE_ERROR(LAYOUT, "Layout constraint violation"), DEFINE_ERROR(MODE, "Incorrect ELF descriptor mode"), DEFINE_ERROR(RANGE, "Value out of range of target"), DEFINE_ERROR(RESOURCE, "Resource exhaustion"), DEFINE_ERROR(SECTION, "Invalid section descriptor"), DEFINE_ERROR(SEQUENCE, "API calls out of sequence"), DEFINE_ERROR(UNIMPL, "Unimplemented feature"), DEFINE_ERROR(VERSION, "Unknown ELF API version"), DEFINE_ERROR(NUM, "Unknown error") #undef DEFINE_ERROR }; const char * elf_errmsg(int error) { int oserr; if (error == ELF_E_NONE && (error = LIBELF_PRIVATE(error)) == 0) return NULL; else if (error == -1) error = LIBELF_PRIVATE(error); oserr = error >> LIBELF_OS_ERROR_SHIFT; error &= LIBELF_ELF_ERROR_MASK; if (error < ELF_E_NONE || error >= ELF_E_NUM) return _libelf_errors[ELF_E_NUM]; if (oserr) { (void) snprintf((char *) LIBELF_PRIVATE(msg), sizeof(LIBELF_PRIVATE(msg)), "%s: %s", _libelf_errors[error], strerror(oserr)); return (const char *)&LIBELF_PRIVATE(msg); } return _libelf_errors[error]; } Index: head/contrib/elftoolchain/libelf/elf_errno.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_errno.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_errno.c (revision 280932) @@ -1,43 +1,41 @@ /*- * Copyright (c) 2006,2008,2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_errno.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_errno.c 3174 2015-03-27 17:13:41Z emaste $"); int elf_errno(void) { int old; old = LIBELF_PRIVATE(error); LIBELF_PRIVATE(error) = 0; return (old & LIBELF_ELF_ERROR_MASK); } Index: head/contrib/elftoolchain/libelf/elf_fill.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_fill.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_fill.c (revision 280932) @@ -1,39 +1,37 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_fill.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_fill.c 3174 2015-03-27 17:13:41Z emaste $"); void elf_fill(int fill) { LIBELF_PRIVATE(fillchar) = fill; } Index: head/contrib/elftoolchain/libelf/elf_flag.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_flag.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_flag.c (revision 280932) @@ -1,198 +1,196 @@ /*- * Copyright (c) 2006,2008-2009,2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_flag.c 2988 2014-03-17 08:51:49Z jkoshy $"); +ELFTC_VCSID("$Id: elf_flag.c 3174 2015-03-27 17:13:41Z emaste $"); unsigned int elf_flagarhdr(Elf_Arhdr *a, Elf_Cmd c, unsigned int flags) { unsigned int r; if (a == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (flags & ~ELF_F_DIRTY) != 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (c == ELF_C_SET) r = a->ar_flags |= flags; else r = a->ar_flags &= ~flags; return (r & LIBELF_F_API_MASK); } unsigned int elf_flagdata(Elf_Data *d, Elf_Cmd c, unsigned int flags) { unsigned int r; struct _Libelf_Data *ld; if (d == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (flags & ~ELF_F_DIRTY) != 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ld = (struct _Libelf_Data *) d; if (c == ELF_C_SET) r = ld->d_flags |= flags; else r = ld->d_flags &= ~flags; return (r & LIBELF_F_API_MASK); } unsigned int elf_flagehdr(Elf *e, Elf_Cmd c, unsigned int flags) { int ec; void *ehdr; if (e == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) ehdr = e->e_u.e_elf.e_ehdr.e_ehdr32; else ehdr = e->e_u.e_elf.e_ehdr.e_ehdr64; if (ehdr == NULL) { LIBELF_SET_ERROR(SEQUENCE, 0); return (0); } return (elf_flagelf(e, c, flags)); } unsigned int elf_flagelf(Elf *e, Elf_Cmd c, unsigned int flags) { unsigned int r; if (e == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (e->e_kind != ELF_K_ELF) || (flags & ~(ELF_F_ARCHIVE | ELF_F_ARCHIVE_SYSV | ELF_F_DIRTY | ELF_F_LAYOUT)) != 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if ((flags & ELF_F_ARCHIVE_SYSV) && (flags & ELF_F_ARCHIVE) == 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if ((flags & ELF_F_ARCHIVE) && e->e_cmd != ELF_C_WRITE) { LIBELF_SET_ERROR(MODE, 0); return (0); } if (c == ELF_C_SET) r = e->e_flags |= flags; else r = e->e_flags &= ~flags; return (r & LIBELF_F_API_MASK); } unsigned int elf_flagphdr(Elf *e, Elf_Cmd c, unsigned int flags) { int ec; void *phdr; if (e == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (e->e_kind != ELF_K_ELF) || (flags & ~ELF_F_DIRTY) != 0 || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) phdr = e->e_u.e_elf.e_phdr.e_phdr32; else phdr = e->e_u.e_elf.e_phdr.e_phdr64; if (phdr == NULL) { LIBELF_SET_ERROR(SEQUENCE, 0); return (0); } return (elf_flagelf(e, c, flags)); } unsigned int elf_flagscn(Elf_Scn *s, Elf_Cmd c, unsigned int flags) { unsigned int r; if (s == NULL) return (0); if ((c != ELF_C_SET && c != ELF_C_CLR) || (flags & ~ELF_F_DIRTY) != 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (c == ELF_C_SET) r = s->s_flags |= flags; else r = s->s_flags &= ~flags; return (r & LIBELF_F_API_MASK); } unsigned int elf_flagshdr(Elf_Scn *s, Elf_Cmd c, unsigned int flags) { return (elf_flagscn(s, c, flags)); } Index: head/contrib/elftoolchain/libelf/elf_getarhdr.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_getarhdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_getarhdr.c (revision 280932) @@ -1,47 +1,45 @@ /*- * Copyright (c) 2006,2008,2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_getarhdr.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_getarhdr.c 3174 2015-03-27 17:13:41Z emaste $"); Elf_Arhdr * elf_getarhdr(Elf *e) { if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (e->e_flags & LIBELF_F_AR_HEADER) return (e->e_hdr.e_arhdr); return (_libelf_ar_gethdr(e)); } Index: head/contrib/elftoolchain/libelf/elf_getarsym.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_getarsym.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_getarsym.c (revision 280932) @@ -1,58 +1,56 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_getarsym.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_getarsym.c 3174 2015-03-27 17:13:41Z emaste $"); Elf_Arsym * elf_getarsym(Elf *ar, size_t *ptr) { size_t n; Elf_Arsym *symtab; n = 0; symtab = NULL; if (ar == NULL || ar->e_kind != ELF_K_AR) LIBELF_SET_ERROR(ARGUMENT, 0); else if ((symtab = ar->e_u.e_ar.e_symtab) != NULL) n = ar->e_u.e_ar.e_symtabsz; else if (ar->e_u.e_ar.e_rawsymtab) symtab = (ar->e_flags & LIBELF_F_AR_VARIANT_SVR4) ? _libelf_ar_process_svr4_symtab(ar, &n) : _libelf_ar_process_bsd_symtab(ar, &n); else LIBELF_SET_ERROR(ARCHIVE, 0); if (ptr) *ptr = n; return (symtab); } Index: head/contrib/elftoolchain/libelf/elf_getbase.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_getbase.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_getbase.c (revision 280932) @@ -1,48 +1,46 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_getbase.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_getbase.c 3174 2015-03-27 17:13:41Z emaste $"); off_t elf_getbase(Elf *e) { if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return ((off_t) -1); } if (e->e_parent == NULL) return ((off_t) 0); return ((off_t) ((uintptr_t) e->e_rawfile - (uintptr_t) e->e_parent->e_rawfile)); } Index: head/contrib/elftoolchain/libelf/elf_getident.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_getident.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_getident.c (revision 280932) @@ -1,68 +1,66 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_getident.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_getident.c 3174 2015-03-27 17:13:41Z emaste $"); char * elf_getident(Elf *e, size_t *sz) { if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); goto error; } if (e->e_cmd == ELF_C_WRITE && e->e_rawfile == NULL) { LIBELF_SET_ERROR(SEQUENCE, 0); goto error; } assert(e->e_kind != ELF_K_AR || e->e_cmd == ELF_C_READ); if (sz) { if (e->e_kind == ELF_K_AR) *sz = SARMAG; else if (e->e_kind == ELF_K_ELF) *sz = EI_NIDENT; else *sz = e->e_rawsize; } return ((char *) e->e_rawfile); error: if (sz) *sz = 0; return (NULL); } Index: head/contrib/elftoolchain/libelf/elf_hash.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_hash.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_hash.c (revision 280932) @@ -1,56 +1,54 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_hash.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_hash.c 3174 2015-03-27 17:13:41Z emaste $"); /* * This elf_hash function is defined by the System V ABI. */ unsigned long elf_hash(const char *name) { unsigned long h, t; const unsigned char *s; s = (const unsigned char *) name; h = t = 0; for (; *s != '\0'; h = h & ~t) { h = (h << 4) + *s++; t = h & 0xF0000000UL; if (t) h ^= t >> 24; } return (h); } Index: head/contrib/elftoolchain/libelf/elf_kind.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_kind.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_kind.c (revision 280932) @@ -1,44 +1,42 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_kind.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_kind.c 3174 2015-03-27 17:13:41Z emaste $"); Elf_Kind elf_kind(Elf *e) { if (e == NULL) return (ELF_K_NONE); if (e->e_kind == ELF_K_AR || e->e_kind == ELF_K_ELF) return (e->e_kind); return (ELF_K_NONE); } Index: head/contrib/elftoolchain/libelf/elf_next.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_next.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_next.c (revision 280932) @@ -1,66 +1,64 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_next.c 2989 2014-03-17 09:56:46Z jkoshy $"); +ELFTC_VCSID("$Id: elf_next.c 3174 2015-03-27 17:13:41Z emaste $"); Elf_Cmd elf_next(Elf *e) { off_t next; Elf *parent; if (e == NULL) return (ELF_C_NULL); if ((parent = e->e_parent) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (ELF_C_NULL); } assert(parent->e_kind == ELF_K_AR); assert(parent->e_cmd == ELF_C_READ); assert(e->e_rawfile > parent->e_rawfile); next = e->e_rawfile - parent->e_rawfile + (off_t) e->e_rawsize; next = (next + 1) & ~1; /* round up to an even boundary */ /* * Setup the 'e_next' field of the archive descriptor for the * next call to 'elf_begin()'. */ parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ? (off_t) 0 : next; return (ELF_C_READ); } Index: head/contrib/elftoolchain/libelf/elf_phnum.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_phnum.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_phnum.c (revision 280932) @@ -1,67 +1,65 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_phnum.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_phnum.c 3174 2015-03-27 17:13:41Z emaste $"); static int _libelf_getphdrnum(Elf *e, size_t *phnum) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (-1); } if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) return (-1); *phnum = e->e_u.e_elf.e_nphdr; return (0); } int elf_getphdrnum(Elf *e, size_t *phnum) { return (_libelf_getphdrnum(e, phnum)); } /* Deprecated API */ int elf_getphnum(Elf *e, size_t *phnum) { return (_libelf_getphdrnum(e, phnum) >= 0); } Index: head/contrib/elftoolchain/libelf/elf_rand.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_rand.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_rand.c (revision 280932) @@ -1,59 +1,57 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_rand.c 2991 2014-03-17 09:57:04Z jkoshy $"); +ELFTC_VCSID("$Id: elf_rand.c 3174 2015-03-27 17:13:41Z emaste $"); off_t elf_rand(Elf *ar, off_t offset) { struct ar_hdr *arh; if (ar == NULL || ar->e_kind != ELF_K_AR || (offset & 1) || offset < SARMAG || (size_t) offset + sizeof(struct ar_hdr) >= ar->e_rawsize) { LIBELF_SET_ERROR(ARGUMENT, 0); return 0; } arh = (struct ar_hdr *) (ar->e_rawfile + offset); /* a too simple sanity check */ if (arh->ar_fmag[0] != '`' || arh->ar_fmag[1] != '\n') { LIBELF_SET_ERROR(ARCHIVE, 0); return 0; } ar->e_u.e_ar.e_next = offset; return (offset); } Index: head/contrib/elftoolchain/libelf/elf_rawfile.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_rawfile.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_rawfile.c (revision 280932) @@ -1,53 +1,51 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_rawfile.c 3013 2014-03-23 06:16:59Z jkoshy $"); +ELFTC_VCSID("$Id: elf_rawfile.c 3174 2015-03-27 17:13:41Z emaste $"); char * elf_rawfile(Elf *e, size_t *sz) { size_t size; unsigned char *ptr; size = e ? e->e_rawsize : 0; ptr = NULL; if (e == NULL) LIBELF_SET_ERROR(ARGUMENT, 0); else if ((ptr = e->e_rawfile) == NULL && e->e_cmd == ELF_C_WRITE) LIBELF_SET_ERROR(SEQUENCE, 0); if (sz) *sz = size; return ((char *) ptr); } Index: head/contrib/elftoolchain/libelf/elf_scn.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_scn.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_scn.c (revision 280932) @@ -1,236 +1,235 @@ /*- * Copyright (c) 2006,2008-2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_scn.c 3147 2015-02-15 18:45:23Z emaste $"); +ELFTC_VCSID("$Id: elf_scn.c 3177 2015-03-30 18:19:41Z emaste $"); /* * Load an ELF section table and create a list of Elf_Scn structures. */ int _libelf_load_section_headers(Elf *e, void *ehdr) { Elf_Scn *scn; uint64_t shoff; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; int ec, swapbytes; unsigned char *src; size_t fsz, i, shnum; int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, size_t _c, int _swap); assert(e != NULL); assert(ehdr != NULL); assert((e->e_flags & LIBELF_F_SHDRS_LOADED) == 0); #define CHECK_EHDR(E,EH) do { \ if (shoff > e->e_rawsize || \ fsz != (EH)->e_shentsize || \ shnum > SIZE_MAX / fsz || \ fsz * shnum > e->e_rawsize - shoff) { \ LIBELF_SET_ERROR(HEADER, 0); \ return (0); \ } \ } while (0) ec = e->e_class; fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, (size_t) 1); assert(fsz > 0); shnum = e->e_u.e_elf.e_nscn; if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; shoff = (uint64_t) eh32->e_shoff; CHECK_EHDR(e, eh32); } else { eh64 = (Elf64_Ehdr *) ehdr; shoff = eh64->e_shoff; CHECK_EHDR(e, eh64); } xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); swapbytes = e->e_byteorder != LIBELF_PRIVATE(byteorder); src = e->e_rawfile + shoff; /* * If the file is using extended numbering then section #0 * would have already been read in. */ i = 0; if (!STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { assert(STAILQ_FIRST(&e->e_u.e_elf.e_scn) == STAILQ_LAST(&e->e_u.e_elf.e_scn, _Elf_Scn, s_next)); i = 1; src += fsz; } for (; i < shnum; i++, src += fsz) { if ((scn = _libelf_allocate_scn(e, i)) == NULL) return (0); (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr), src, (size_t) 1, swapbytes); if (ec == ELFCLASS32) { scn->s_offset = scn->s_rawoff = scn->s_shdr.s_shdr32.sh_offset; scn->s_size = scn->s_shdr.s_shdr32.sh_size; } else { scn->s_offset = scn->s_rawoff = scn->s_shdr.s_shdr64.sh_offset; scn->s_size = scn->s_shdr.s_shdr64.sh_size; } } e->e_flags |= LIBELF_F_SHDRS_LOADED; return (1); } Elf_Scn * elf_getscn(Elf *e, size_t index) { int ec; void *ehdr; Elf_Scn *s; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); if (e->e_cmd != ELF_C_WRITE && (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && _libelf_load_section_headers(e, ehdr) == 0) return (NULL); STAILQ_FOREACH(s, &e->e_u.e_elf.e_scn, s_next) if (s->s_ndx == index) return (s); LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } size_t elf_ndxscn(Elf_Scn *s) { if (s == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (SHN_UNDEF); } return (s->s_ndx); } Elf_Scn * elf_newscn(Elf *e) { int ec; void *ehdr; Elf_Scn *scn; if (e == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); /* * The application may be asking for a new section descriptor * on an ELF object opened with ELF_C_RDWR or ELF_C_READ. We * need to bring in the existing section information before * appending a new one to the list. * * Per the ELF(3) API, an application is allowed to open a * file using ELF_C_READ, mess with its internal structure and * use elf_update(...,ELF_C_NULL) to compute its new layout. */ if (e->e_cmd != ELF_C_WRITE && (e->e_flags & LIBELF_F_SHDRS_LOADED) == 0 && _libelf_load_section_headers(e, ehdr) == 0) return (NULL); if (STAILQ_EMPTY(&e->e_u.e_elf.e_scn)) { assert(e->e_u.e_elf.e_nscn == 0); if ((scn = _libelf_allocate_scn(e, (size_t) SHN_UNDEF)) == NULL) return (NULL); e->e_u.e_elf.e_nscn++; } assert(e->e_u.e_elf.e_nscn > 0); if ((scn = _libelf_allocate_scn(e, e->e_u.e_elf.e_nscn)) == NULL) return (NULL); e->e_u.e_elf.e_nscn++; (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); return (scn); } Elf_Scn * elf_nextscn(Elf *e, Elf_Scn *s) { if (e == NULL || (e->e_kind != ELF_K_ELF) || (s && s->s_elf != e)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } return (s == NULL ? elf_getscn(e, (size_t) 1) : STAILQ_NEXT(s, s_next)); } Index: head/contrib/elftoolchain/libelf/elf_shnum.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_shnum.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_shnum.c (revision 280932) @@ -1,67 +1,65 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_shnum.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_shnum.c 3174 2015-03-27 17:13:41Z emaste $"); static int _libelf_getshdrnum(Elf *e, size_t *shnum) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (-1); } if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) return (-1); *shnum = e->e_u.e_elf.e_nscn; return (0); } int elf_getshdrnum(Elf *e, size_t *shnum) { return (_libelf_getshdrnum(e, shnum)); } /* Deprecated API. */ int elf_getshnum(Elf *e, size_t *shnum) { return (_libelf_getshdrnum(e, shnum) >= 0); } Index: head/contrib/elftoolchain/libelf/elf_shstrndx.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_shstrndx.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_shstrndx.c (revision 280932) @@ -1,82 +1,80 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_shstrndx.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_shstrndx.c 3174 2015-03-27 17:13:41Z emaste $"); static int _libelf_getshdrstrndx(Elf *e, size_t *strndx) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (-1); } if ((eh = _libelf_ehdr(e, ec, 0)) == NULL) return (-1); *strndx = e->e_u.e_elf.e_strndx; return (0); } int elf_getshdrstrndx(Elf *e, size_t *strndx) { return (_libelf_getshdrstrndx(e, strndx)); } int elf_getshstrndx(Elf *e, size_t *strndx) /* Deprecated API. */ { return (_libelf_getshdrstrndx(e, strndx) >= 0); } int elf_setshstrndx(Elf *e, size_t strndx) { void *eh; int ec; if (e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || ((eh = _libelf_ehdr(e, ec, 0)) == NULL)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } return (_libelf_setshstrndx(e, eh, ec, strndx)); } Index: head/contrib/elftoolchain/libelf/elf_version.c =================================================================== --- head/contrib/elftoolchain/libelf/elf_version.c (revision 280931) +++ head/contrib/elftoolchain/libelf/elf_version.c (revision 280932) @@ -1,52 +1,50 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: elf_version.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: elf_version.c 3174 2015-03-27 17:13:41Z emaste $"); unsigned int elf_version(unsigned int v) { unsigned int old; if ((old = LIBELF_PRIVATE(version)) == EV_NONE) old = EV_CURRENT; if (v == EV_NONE) return old; if (v > EV_CURRENT) { LIBELF_SET_ERROR(VERSION, 0); return EV_NONE; } LIBELF_PRIVATE(version) = v; return (old); } Index: head/contrib/elftoolchain/libelf/gelf.h =================================================================== --- head/contrib/elftoolchain/libelf/gelf.h (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf.h (revision 280932) @@ -1,108 +1,110 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: gelf.h 1168 2010-09-04 01:03:25Z jkoshy $ + * $Id: gelf.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef _GELF_H_ #define _GELF_H_ -#include - #include typedef Elf64_Addr GElf_Addr; /* Addresses */ typedef Elf64_Half GElf_Half; /* Half words (16 bit) */ typedef Elf64_Off GElf_Off; /* Offsets */ typedef Elf64_Sword GElf_Sword; /* Signed words (32 bit) */ typedef Elf64_Sxword GElf_Sxword; /* Signed long words (64 bit) */ typedef Elf64_Word GElf_Word; /* Unsigned words (32 bit) */ typedef Elf64_Xword GElf_Xword; /* Unsigned long words (64 bit) */ typedef Elf64_Dyn GElf_Dyn; /* ".dynamic" section entries */ typedef Elf64_Ehdr GElf_Ehdr; /* ELF header */ typedef Elf64_Phdr GElf_Phdr; /* Program header */ typedef Elf64_Shdr GElf_Shdr; /* Section header */ typedef Elf64_Sym GElf_Sym; /* Symbol table entries */ typedef Elf64_Rel GElf_Rel; /* Relocation entries */ typedef Elf64_Rela GElf_Rela; /* Relocation entries with addend */ typedef Elf64_Cap GElf_Cap; /* SW/HW capabilities */ typedef Elf64_Move GElf_Move; /* Move entries */ typedef Elf64_Syminfo GElf_Syminfo; /* Symbol information */ #define GELF_M_INFO ELF64_M_INFO #define GELF_M_SIZE ELF64_M_SIZE #define GELF_M_SYM ELF64_M_SYM #define GELF_R_INFO ELF64_R_INFO #define GELF_R_SYM ELF64_R_SYM #define GELF_R_TYPE ELF64_R_TYPE #define GELF_R_TYPE_DATA ELF64_R_TYPE_DATA #define GELF_R_TYPE_ID ELF64_R_TYPE_ID #define GELF_R_TYPE_INFO ELF64_R_TYPE_INFO #define GELF_ST_BIND ELF64_ST_BIND #define GELF_ST_INFO ELF64_ST_INFO #define GELF_ST_TYPE ELF64_ST_TYPE #define GELF_ST_VISIBILITY ELF64_ST_VISIBILITY -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif long gelf_checksum(Elf *_elf); size_t gelf_fsize(Elf *_elf, Elf_Type _type, size_t _count, unsigned int _version); int gelf_getclass(Elf *_elf); GElf_Dyn *gelf_getdyn(Elf_Data *_data, int _index, GElf_Dyn *_dst); GElf_Ehdr *gelf_getehdr(Elf *_elf, GElf_Ehdr *_dst); GElf_Phdr *gelf_getphdr(Elf *_elf, int _index, GElf_Phdr *_dst); GElf_Rel *gelf_getrel(Elf_Data *_src, int _index, GElf_Rel *_dst); GElf_Rela *gelf_getrela(Elf_Data *_src, int _index, GElf_Rela *_dst); GElf_Shdr *gelf_getshdr(Elf_Scn *_scn, GElf_Shdr *_dst); GElf_Sym *gelf_getsym(Elf_Data *_src, int _index, GElf_Sym *_dst); GElf_Sym *gelf_getsymshndx(Elf_Data *_src, Elf_Data *_shindexsrc, int _index, GElf_Sym *_dst, Elf32_Word *_shindexdst); void * gelf_newehdr(Elf *_elf, int _class); void * gelf_newphdr(Elf *_elf, size_t _phnum); int gelf_update_dyn(Elf_Data *_dst, int _index, GElf_Dyn *_src); int gelf_update_ehdr(Elf *_elf, GElf_Ehdr *_src); int gelf_update_phdr(Elf *_elf, int _index, GElf_Phdr *_src); int gelf_update_rel(Elf_Data *_dst, int _index, GElf_Rel *_src); int gelf_update_rela(Elf_Data *_dst, int _index, GElf_Rela *_src); int gelf_update_shdr(Elf_Scn *_dst, GElf_Shdr *_src); int gelf_update_sym(Elf_Data *_dst, int _index, GElf_Sym *_src); int gelf_update_symshndx(Elf_Data *_symdst, Elf_Data *_shindexdst, int _index, GElf_Sym *_symsrc, Elf32_Word _shindexsrc); Elf_Data *gelf_xlatetof(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); Elf_Data *gelf_xlatetom(Elf *_elf, Elf_Data *_dst, const Elf_Data *_src, unsigned int _encode); GElf_Cap *gelf_getcap(Elf_Data *_data, int _index, GElf_Cap *_cap); GElf_Move *gelf_getmove(Elf_Data *_src, int _index, GElf_Move *_dst); GElf_Syminfo *gelf_getsyminfo(Elf_Data *_src, int _index, GElf_Syminfo *_dst); int gelf_update_cap(Elf_Data *_dst, int _index, GElf_Cap *_src); int gelf_update_move(Elf_Data *_dst, int _index, GElf_Move *_src); int gelf_update_syminfo(Elf_Data *_dst, int _index, GElf_Syminfo *_src); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* _GELF_H_ */ Index: head/contrib/elftoolchain/libelf/gelf_cap.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_cap.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_cap.c (revision 280932) @@ -1,152 +1,150 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_cap.c 2995 2014-03-18 02:16:31Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_cap.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Cap * gelf_getcap(Elf_Data *ed, int ndx, GElf_Cap *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; Elf32_Cap *cap32; Elf64_Cap *cap64; uint32_t sh_type; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); assert(msz > 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { cap32 = (Elf32_Cap *) d->d_data.d_buf + ndx; dst->c_tag = cap32->c_tag; dst->c_un.c_val = (Elf64_Xword) cap32->c_un.c_val; } else { cap64 = (Elf64_Cap *) d->d_data.d_buf + ndx; *dst = *cap64; } return (dst); } int gelf_update_cap(Elf_Data *ed, int ndx, GElf_Cap *gc) { int ec; Elf *e; size_t msz; Elf_Scn *scn; Elf32_Cap *cap32; Elf64_Cap *cap64; uint32_t sh_type; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || gc == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_CAP) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_CAP, ec, e->e_version); assert(msz > 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { cap32 = (Elf32_Cap *) d->d_data.d_buf + ndx; LIBELF_COPY_U32(cap32, gc, c_tag); LIBELF_COPY_U32(cap32, gc, c_un.c_val); } else { cap64 = (Elf64_Cap *) d->d_data.d_buf + ndx; *cap64 = *gc; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_checksum.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_checksum.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_checksum.c (revision 280932) @@ -1,58 +1,56 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_checksum.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_checksum.c 3174 2015-03-27 17:13:41Z emaste $"); long elf32_checksum(Elf *e) { return (_libelf_checksum(e, ELFCLASS32)); } long elf64_checksum(Elf *e) { return (_libelf_checksum(e, ELFCLASS64)); } long gelf_checksum(Elf *e) { int ec; if (e == NULL || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0L); } return (_libelf_checksum(e, ec)); } Index: head/contrib/elftoolchain/libelf/gelf_dyn.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_dyn.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_dyn.c (revision 280932) @@ -1,154 +1,152 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_dyn.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_dyn.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Dyn * gelf_getdyn(Elf_Data *ed, int ndx, GElf_Dyn *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; Elf32_Dyn *dyn32; Elf64_Dyn *dyn64; uint32_t sh_type; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { dyn32 = (Elf32_Dyn *) d->d_data.d_buf + ndx; dst->d_tag = dyn32->d_tag; dst->d_un.d_val = (Elf64_Xword) dyn32->d_un.d_val; } else { dyn64 = (Elf64_Dyn *) d->d_data.d_buf + ndx; *dst = *dyn64; } return (dst); } int gelf_update_dyn(Elf_Data *ed, int ndx, GElf_Dyn *ds) { int ec; Elf *e; size_t msz; Elf_Scn *scn; Elf32_Dyn *dyn32; Elf64_Dyn *dyn64; uint32_t sh_type; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || ds == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_DYN) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_DYN, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { dyn32 = (Elf32_Dyn *) d->d_data.d_buf + ndx; LIBELF_COPY_S32(dyn32, ds, d_tag); LIBELF_COPY_U32(dyn32, ds, d_un.d_val); } else { dyn64 = (Elf64_Dyn *) d->d_data.d_buf + ndx; *dyn64 = *ds; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_ehdr.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_ehdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_ehdr.c (revision 280932) @@ -1,169 +1,167 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_ehdr.c 2268 2011-12-03 17:05:11Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_ehdr.c 3177 2015-03-30 18:19:41Z emaste $"); Elf32_Ehdr * elf32_getehdr(Elf *e) { return (_libelf_ehdr(e, ELFCLASS32, 0)); } Elf64_Ehdr * elf64_getehdr(Elf *e) { return (_libelf_ehdr(e, ELFCLASS64, 0)); } GElf_Ehdr * gelf_getehdr(Elf *e, GElf_Ehdr *d) { int ec; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; if (d == NULL || e == NULL || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL) return (NULL); (void) memcpy(d->e_ident, eh32->e_ident, sizeof(eh32->e_ident)); d->e_type = eh32->e_type; d->e_machine = eh32->e_machine; d->e_version = eh32->e_version; d->e_entry = eh32->e_entry; d->e_phoff = eh32->e_phoff; d->e_shoff = eh32->e_shoff; d->e_flags = eh32->e_flags; d->e_ehsize = eh32->e_ehsize; d->e_phentsize = eh32->e_phentsize; d->e_phnum = eh32->e_phnum; d->e_shentsize = eh32->e_shentsize; d->e_shnum = eh32->e_shnum; d->e_shstrndx = eh32->e_shstrndx; return (d); } assert(ec == ELFCLASS64); if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL) return (NULL); *d = *eh64; return (d); } Elf32_Ehdr * elf32_newehdr(Elf *e) { return (_libelf_ehdr(e, ELFCLASS32, 1)); } Elf64_Ehdr * elf64_newehdr(Elf *e) { return (_libelf_ehdr(e, ELFCLASS64, 1)); } void * gelf_newehdr(Elf *e, int ec) { if (e != NULL && (ec == ELFCLASS32 || ec == ELFCLASS64)) return (_libelf_ehdr(e, ec, 1)); LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } int gelf_update_ehdr(Elf *e, GElf_Ehdr *s) { int ec; void *ehdr; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; if (s== NULL || e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (0); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (0); (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); if (ec == ELFCLASS64) { eh64 = (Elf64_Ehdr *) ehdr; *eh64 = *s; return (1); } eh32 = (Elf32_Ehdr *) ehdr; (void) memcpy(eh32->e_ident, s->e_ident, sizeof(eh32->e_ident)); eh32->e_type = s->e_type; eh32->e_machine = s->e_machine; eh32->e_version = s->e_version; LIBELF_COPY_U32(eh32, s, e_entry); LIBELF_COPY_U32(eh32, s, e_phoff); LIBELF_COPY_U32(eh32, s, e_shoff); eh32->e_flags = s->e_flags; eh32->e_ehsize = s->e_ehsize; eh32->e_phentsize = s->e_phentsize; eh32->e_phnum = s->e_phnum; eh32->e_shentsize = s->e_shentsize; eh32->e_shnum = s->e_shnum; eh32->e_shstrndx = s->e_shstrndx; return (1); } Index: head/contrib/elftoolchain/libelf/gelf_fsize.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_fsize.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_fsize.c (revision 280932) @@ -1,62 +1,60 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_fsize.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_fsize.c 3174 2015-03-27 17:13:41Z emaste $"); size_t elf32_fsize(Elf_Type t, size_t c, unsigned int v) { return (_libelf_fsize(t, ELFCLASS32, v, c)); } size_t elf64_fsize(Elf_Type t, size_t c, unsigned int v) { return (_libelf_fsize(t, ELFCLASS64, v, c)); } size_t gelf_fsize(Elf *e, Elf_Type t, size_t c, unsigned int v) { if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (e->e_class == ELFCLASS32 || e->e_class == ELFCLASS64) return (_libelf_fsize(t, e->e_class, v, c)); LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } Index: head/contrib/elftoolchain/libelf/gelf_getclass.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_getclass.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_getclass.c (revision 280932) @@ -1,39 +1,37 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_getclass.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_getclass.c 3174 2015-03-27 17:13:41Z emaste $"); int gelf_getclass(Elf *e) { return (e != NULL ? e->e_class : ELFCLASSNONE); } Index: head/contrib/elftoolchain/libelf/gelf_move.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_move.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_move.c (revision 280932) @@ -1,161 +1,159 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_move.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_move.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Move * gelf_getmove(Elf_Data *ed, int ndx, GElf_Move *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Move *move32; Elf64_Move *move64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { move32 = (Elf32_Move *) d->d_data.d_buf + ndx; dst->m_value = move32->m_value; dst->m_info = (Elf64_Xword) move32->m_info; dst->m_poffset = (Elf64_Xword) move32->m_poffset; dst->m_repeat = move32->m_repeat; dst->m_stride = move32->m_stride; } else { move64 = (Elf64_Move *) d->d_data.d_buf + ndx; *dst = *move64; } return (dst); } int gelf_update_move(Elf_Data *ed, int ndx, GElf_Move *gm) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Move *move32; Elf64_Move *move64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || gm == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_MOVE) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_MOVE, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { move32 = (Elf32_Move *) d->d_data.d_buf + ndx; move32->m_value = gm->m_value; LIBELF_COPY_U32(move32, gm, m_info); LIBELF_COPY_U32(move32, gm, m_poffset); move32->m_repeat = gm->m_repeat; move32->m_stride = gm->m_stride; } else { move64 = (Elf64_Move *) d->d_data.d_buf + ndx; *move64 = *gm; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_phdr.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_phdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_phdr.c (revision 280932) @@ -1,179 +1,177 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_phdr.c 2268 2011-12-03 17:05:11Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_phdr.c 3177 2015-03-30 18:19:41Z emaste $"); Elf32_Phdr * elf32_getphdr(Elf *e) { return (_libelf_getphdr(e, ELFCLASS32)); } Elf64_Phdr * elf64_getphdr(Elf *e) { return (_libelf_getphdr(e, ELFCLASS64)); } GElf_Phdr * gelf_getphdr(Elf *e, int index, GElf_Phdr *d) { int ec; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; Elf32_Phdr *ep32; Elf64_Phdr *ep64; if (d == NULL || e == NULL || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64) || (e->e_kind != ELF_K_ELF) || index < 0) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { if ((eh32 = _libelf_ehdr(e, ELFCLASS32, 0)) == NULL || ((ep32 = _libelf_getphdr(e, ELFCLASS32)) == NULL)) return (NULL); if (index >= eh32->e_phnum) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ep32 += index; d->p_type = ep32->p_type; d->p_offset = ep32->p_offset; d->p_vaddr = (Elf64_Addr) ep32->p_vaddr; d->p_paddr = (Elf64_Addr) ep32->p_paddr; d->p_filesz = (Elf64_Xword) ep32->p_filesz; d->p_memsz = (Elf64_Xword) ep32->p_memsz; d->p_flags = ep32->p_flags; d->p_align = (Elf64_Xword) ep32->p_align; } else { if ((eh64 = _libelf_ehdr(e, ELFCLASS64, 0)) == NULL || (ep64 = _libelf_getphdr(e, ELFCLASS64)) == NULL) return (NULL); if (index >= eh64->e_phnum) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ep64 += index; *d = *ep64; } return (d); } Elf32_Phdr * elf32_newphdr(Elf *e, size_t count) { return (_libelf_newphdr(e, ELFCLASS32, count)); } Elf64_Phdr * elf64_newphdr(Elf *e, size_t count) { return (_libelf_newphdr(e, ELFCLASS64, count)); } void * gelf_newphdr(Elf *e, size_t count) { if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } return (_libelf_newphdr(e, e->e_class, count)); } int gelf_update_phdr(Elf *e, int ndx, GElf_Phdr *s) { int ec, phnum; void *ehdr; Elf32_Phdr *ph32; Elf64_Phdr *ph64; if (s == NULL || e == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (0); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (0); if (ec == ELFCLASS32) phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; else phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; if (ndx < 0 || ndx > phnum) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } (void) elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); if (ec == ELFCLASS64) { ph64 = e->e_u.e_elf.e_phdr.e_phdr64 + ndx; *ph64 = *s; return (1); } ph32 = e->e_u.e_elf.e_phdr.e_phdr32 + ndx; ph32->p_type = s->p_type; ph32->p_flags = s->p_flags; LIBELF_COPY_U32(ph32, s, p_offset); LIBELF_COPY_U32(ph32, s, p_vaddr); LIBELF_COPY_U32(ph32, s, p_paddr); LIBELF_COPY_U32(ph32, s, p_filesz); LIBELF_COPY_U32(ph32, s, p_memsz); LIBELF_COPY_U32(ph32, s, p_align); return (1); } Index: head/contrib/elftoolchain/libelf/gelf_rel.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_rel.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_rel.c (revision 280932) @@ -1,164 +1,162 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_rel.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_rel.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Rel * gelf_getrel(Elf_Data *ed, int ndx, GElf_Rel *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Rel *rel32; Elf64_Rel *rel64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_REL, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx; dst->r_offset = (Elf64_Addr) rel32->r_offset; dst->r_info = ELF64_R_INFO( (Elf64_Xword) ELF32_R_SYM(rel32->r_info), ELF32_R_TYPE(rel32->r_info)); } else { rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx; *dst = *rel64; } return (dst); } int gelf_update_rel(Elf_Data *ed, int ndx, GElf_Rel *dr) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Rel *rel32; Elf64_Rel *rel64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dr == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_REL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_REL, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { rel32 = (Elf32_Rel *) d->d_data.d_buf + ndx; LIBELF_COPY_U32(rel32, dr, r_offset); if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) || ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) { LIBELF_SET_ERROR(RANGE, 0); return (0); } rel32->r_info = ELF32_R_INFO( (Elf32_Word) ELF64_R_SYM(dr->r_info), (Elf32_Word) ELF64_R_TYPE(dr->r_info)); } else { rel64 = (Elf64_Rel *) d->d_data.d_buf + ndx; *rel64 = *dr; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_rela.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_rela.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_rela.c (revision 280932) @@ -1,167 +1,165 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_rela.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_rela.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Rela * gelf_getrela(Elf_Data *ed, int ndx, GElf_Rela *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Rela *rela32; Elf64_Rela *rela64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { rela32 = (Elf32_Rela *) d->d_data.d_buf + ndx; dst->r_offset = (Elf64_Addr) rela32->r_offset; dst->r_info = ELF64_R_INFO( (Elf64_Xword) ELF32_R_SYM(rela32->r_info), ELF32_R_TYPE(rela32->r_info)); dst->r_addend = (Elf64_Sxword) rela32->r_addend; } else { rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx; *dst = *rela64; } return (dst); } int gelf_update_rela(Elf_Data *ed, int ndx, GElf_Rela *dr) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Rela *rela32; Elf64_Rela *rela64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dr == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_RELA) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_RELA, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { rela32 = (Elf32_Rela *) d->d_data.d_buf + ndx; LIBELF_COPY_U32(rela32, dr, r_offset); if (ELF64_R_SYM(dr->r_info) > ELF32_R_SYM(~0UL) || ELF64_R_TYPE(dr->r_info) > ELF32_R_TYPE(~0U)) { LIBELF_SET_ERROR(RANGE, 0); return (0); } rela32->r_info = ELF32_R_INFO( (Elf32_Word) ELF64_R_SYM(dr->r_info), (Elf32_Word) ELF64_R_TYPE(dr->r_info)); LIBELF_COPY_S32(rela32, dr, r_addend); } else { rela64 = (Elf64_Rela *) d->d_data.d_buf + ndx; *rela64 = *dr; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_shdr.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_shdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_shdr.c (revision 280932) @@ -1,132 +1,130 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_shdr.c 2268 2011-12-03 17:05:11Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_shdr.c 3177 2015-03-30 18:19:41Z emaste $"); Elf32_Shdr * elf32_getshdr(Elf_Scn *s) { return (_libelf_getshdr(s, ELFCLASS32)); } Elf64_Shdr * elf64_getshdr(Elf_Scn *s) { return (_libelf_getshdr(s, ELFCLASS64)); } GElf_Shdr * gelf_getshdr(Elf_Scn *s, GElf_Shdr *d) { int ec; void *sh; Elf32_Shdr *sh32; Elf64_Shdr *sh64; if (d == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((sh = _libelf_getshdr(s, ELFCLASSNONE)) == NULL) return (NULL); ec = s->s_elf->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) { sh32 = (Elf32_Shdr *) sh; d->sh_name = sh32->sh_name; d->sh_type = sh32->sh_type; d->sh_flags = (Elf64_Xword) sh32->sh_flags; d->sh_addr = (Elf64_Addr) sh32->sh_addr; d->sh_offset = (Elf64_Off) sh32->sh_offset; d->sh_size = (Elf64_Xword) sh32->sh_size; d->sh_link = sh32->sh_link; d->sh_info = sh32->sh_info; d->sh_addralign = (Elf64_Xword) sh32->sh_addralign; d->sh_entsize = (Elf64_Xword) sh32->sh_entsize; } else { sh64 = (Elf64_Shdr *) sh; *d = *sh64; } return (d); } int gelf_update_shdr(Elf_Scn *scn, GElf_Shdr *s) { int ec; Elf *e; Elf32_Shdr *sh32; if (s == NULL || scn == NULL || (e = scn->s_elf) == NULL || e->e_kind != ELF_K_ELF || ((ec = e->e_class) != ELFCLASS32 && ec != ELFCLASS64)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (e->e_cmd == ELF_C_READ) { LIBELF_SET_ERROR(MODE, 0); return (0); } (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); if (ec == ELFCLASS64) { scn->s_shdr.s_shdr64 = *s; return (1); } sh32 = &scn->s_shdr.s_shdr32; sh32->sh_name = s->sh_name; sh32->sh_type = s->sh_type; LIBELF_COPY_U32(sh32, s, sh_flags); LIBELF_COPY_U32(sh32, s, sh_addr); LIBELF_COPY_U32(sh32, s, sh_offset); LIBELF_COPY_U32(sh32, s, sh_size); sh32->sh_link = s->sh_link; sh32->sh_info = s->sh_info; LIBELF_COPY_U32(sh32, s, sh_addralign); LIBELF_COPY_U32(sh32, s, sh_entsize); return (1); } Index: head/contrib/elftoolchain/libelf/gelf_sym.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_sym.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_sym.c (revision 280932) @@ -1,161 +1,159 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_sym.c 2999 2014-03-18 17:19:06Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_sym.c 3177 2015-03-30 18:19:41Z emaste $"); GElf_Sym * gelf_getsym(Elf_Data *ed, int ndx, GElf_Sym *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Sym *sym32; Elf64_Sym *sym64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx; dst->st_name = sym32->st_name; dst->st_value = (Elf64_Addr) sym32->st_value; dst->st_size = (Elf64_Xword) sym32->st_size; dst->st_info = sym32->st_info; dst->st_other = sym32->st_other; dst->st_shndx = sym32->st_shndx; } else { sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx; *dst = *sym64; } return (dst); } int gelf_update_sym(Elf_Data *ed, int ndx, GElf_Sym *gs) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; Elf32_Sym *sym32; Elf64_Sym *sym64; struct _Libelf_Data *d; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || gs == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYM) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_SYM, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { sym32 = (Elf32_Sym *) d->d_data.d_buf + ndx; sym32->st_name = gs->st_name; sym32->st_info = gs->st_info; sym32->st_other = gs->st_other; sym32->st_shndx = gs->st_shndx; LIBELF_COPY_U32(sym32, gs, st_value); LIBELF_COPY_U32(sym32, gs, st_size); } else { sym64 = (Elf64_Sym *) d->d_data.d_buf + ndx; *sym64 = *gs; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_syminfo.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_syminfo.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_syminfo.c (revision 280932) @@ -1,154 +1,152 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_syminfo.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_syminfo.c 3174 2015-03-27 17:13:41Z emaste $"); GElf_Syminfo * gelf_getsyminfo(Elf_Data *ed, int ndx, GElf_Syminfo *dst) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; struct _Libelf_Data *d; Elf32_Syminfo *syminfo32; Elf64_Syminfo *syminfo64; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || dst == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASS32) { syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx; dst->si_boundto = syminfo32->si_boundto; dst->si_flags = syminfo32->si_flags; } else { syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx; *dst = *syminfo64; } return (dst); } int gelf_update_syminfo(Elf_Data *ed, int ndx, GElf_Syminfo *gs) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; struct _Libelf_Data *d; Elf32_Syminfo *syminfo32; Elf64_Syminfo *syminfo64; d = (struct _Libelf_Data *) ed; if (d == NULL || ndx < 0 || gs == NULL || (scn = d->d_scn) == NULL || (e = scn->s_elf) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_SYMINFO) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_SYMINFO, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= d->d_data.d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } if (ec == ELFCLASS32) { syminfo32 = (Elf32_Syminfo *) d->d_data.d_buf + ndx; syminfo32->si_boundto = gs->si_boundto; syminfo32->si_flags = gs->si_flags; } else { syminfo64 = (Elf64_Syminfo *) d->d_data.d_buf + ndx; *syminfo64 = *gs; } return (1); } Index: head/contrib/elftoolchain/libelf/gelf_symshndx.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_symshndx.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_symshndx.c (revision 280932) @@ -1,139 +1,137 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_symshndx.c 2998 2014-03-18 17:19:00Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_symshndx.c 3174 2015-03-27 17:13:41Z emaste $"); GElf_Sym * gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst, Elf32_Word *shindex) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; struct _Libelf_Data *ld, *lid; ld = (struct _Libelf_Data *) d; lid = (struct _Libelf_Data *) id; if (gelf_getsym(d, ndx, dst) == 0) return (NULL); if (lid == NULL || (scn = lid->d_scn) == NULL || (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf) || shindex == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || id->d_type != ELF_T_WORD) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= id->d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } *shindex = ((Elf32_Word *) id->d_buf)[ndx]; return (dst); } int gelf_update_symshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *gs, Elf32_Word xindex) { int ec; Elf *e; size_t msz; Elf_Scn *scn; uint32_t sh_type; struct _Libelf_Data *ld, *lid; ld = (struct _Libelf_Data *) d; lid = (struct _Libelf_Data *) id; if (gelf_update_sym(d, ndx, gs) == 0) return (0); if (lid == NULL || (scn = lid->d_scn) == NULL || (e = scn->s_elf) == NULL || (e != ld->d_scn->s_elf)) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } ec = e->e_class; assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (ec == ELFCLASS32) sh_type = scn->s_shdr.s_shdr32.sh_type; else sh_type = scn->s_shdr.s_shdr64.sh_type; if (_libelf_xlate_shtype(sh_type) != ELF_T_WORD || d->d_type != ELF_T_WORD) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } msz = _libelf_msize(ELF_T_WORD, ec, e->e_version); assert(msz > 0); assert(ndx >= 0); if (msz * (size_t) ndx >= id->d_size) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0); } *(((Elf32_Word *) id->d_buf) + ndx) = xindex; return (1); } Index: head/contrib/elftoolchain/libelf/gelf_xlate.c =================================================================== --- head/contrib/elftoolchain/libelf/gelf_xlate.c (revision 280931) +++ head/contrib/elftoolchain/libelf/gelf_xlate.c (revision 280932) @@ -1,81 +1,79 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: gelf_xlate.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: gelf_xlate.c 3174 2015-03-27 17:13:41Z emaste $"); Elf_Data * elf32_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOFILE); } Elf_Data * elf64_xlatetof(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOFILE); } Elf_Data * elf32_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { return _libelf_xlate(dst, src, encoding, ELFCLASS32, ELF_TOMEMORY); } Elf_Data * elf64_xlatetom(Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { return _libelf_xlate(dst, src, encoding, ELFCLASS64, ELF_TOMEMORY); } Elf_Data * gelf_xlatetom(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { if (e != NULL) return (_libelf_xlate(dst, src, encoding, e->e_class, ELF_TOMEMORY)); LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } Elf_Data * gelf_xlatetof(Elf *e, Elf_Data *dst, const Elf_Data *src, unsigned int encoding) { if (e != NULL) return (_libelf_xlate(dst, src, encoding, e->e_class, ELF_TOFILE)); LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } Index: head/contrib/elftoolchain/libelf/libelf.h =================================================================== --- head/contrib/elftoolchain/libelf/libelf.h (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf.h (revision 280932) @@ -1,252 +1,256 @@ /*- * Copyright (c) 2006,2008-2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: libelf.h 2988 2014-03-17 08:51:49Z jkoshy $ + * $Id: libelf.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef _LIBELF_H_ #define _LIBELF_H_ #include #include #include /* Library private data structures */ typedef struct _Elf Elf; typedef struct _Elf_Scn Elf_Scn; /* File types */ typedef enum { ELF_K_NONE = 0, ELF_K_AR, /* `ar' archives */ ELF_K_COFF, /* COFF files (unsupported) */ ELF_K_ELF, /* ELF files */ ELF_K_NUM } Elf_Kind; #define ELF_K_FIRST ELF_K_NONE #define ELF_K_LAST ELF_K_NUM /* Data types */ typedef enum { ELF_T_ADDR, ELF_T_BYTE, ELF_T_CAP, ELF_T_DYN, ELF_T_EHDR, ELF_T_HALF, ELF_T_LWORD, ELF_T_MOVE, ELF_T_MOVEP, ELF_T_NOTE, ELF_T_OFF, ELF_T_PHDR, ELF_T_REL, ELF_T_RELA, ELF_T_SHDR, ELF_T_SWORD, ELF_T_SXWORD, ELF_T_SYMINFO, ELF_T_SYM, ELF_T_VDEF, ELF_T_VNEED, ELF_T_WORD, ELF_T_XWORD, ELF_T_GNUHASH, /* GNU style hash tables. */ ELF_T_NUM } Elf_Type; #define ELF_T_FIRST ELF_T_ADDR #define ELF_T_LAST ELF_T_GNUHASH /* Commands */ typedef enum { ELF_C_NULL = 0, ELF_C_CLR, ELF_C_FDDONE, ELF_C_FDREAD, ELF_C_RDWR, ELF_C_READ, ELF_C_SET, ELF_C_WRITE, ELF_C_NUM } Elf_Cmd; #define ELF_C_FIRST ELF_C_NULL #define ELF_C_LAST ELF_C_NUM /* * An `Elf_Data' structure describes data in an * ELF section. */ typedef struct _Elf_Data { /* * `Public' members that are part of the ELF(3) API. */ uint64_t d_align; void *d_buf; uint64_t d_off; uint64_t d_size; Elf_Type d_type; unsigned int d_version; } Elf_Data; /* * An `Elf_Arhdr' structure describes an archive * header. */ typedef struct { time_t ar_date; char *ar_name; /* archive member name */ gid_t ar_gid; mode_t ar_mode; char *ar_rawname; /* 'raw' member name */ size_t ar_size; uid_t ar_uid; /* * Members that are not part of the public API. */ unsigned int ar_flags; } Elf_Arhdr; /* * An `Elf_Arsym' describes an entry in the archive * symbol table. */ typedef struct { off_t as_off; /* byte offset to member's header */ unsigned long as_hash; /* elf_hash() value for name */ char *as_name; /* null terminated symbol name */ } Elf_Arsym; /* * Error numbers. */ enum Elf_Error { ELF_E_NONE, /* No error */ ELF_E_ARCHIVE, /* Malformed ar(1) archive */ ELF_E_ARGUMENT, /* Invalid argument */ ELF_E_CLASS, /* Mismatched ELF class */ ELF_E_DATA, /* Invalid data descriptor */ ELF_E_HEADER, /* Missing or malformed ELF header */ ELF_E_IO, /* I/O error */ ELF_E_LAYOUT, /* Layout constraint violation */ ELF_E_MODE, /* Wrong mode for ELF descriptor */ ELF_E_RANGE, /* Value out of range */ ELF_E_RESOURCE, /* Resource exhaustion */ ELF_E_SECTION, /* Invalid section descriptor */ ELF_E_SEQUENCE, /* API calls out of sequence */ ELF_E_UNIMPL, /* Feature is unimplemented */ ELF_E_VERSION, /* Unknown API version */ ELF_E_NUM /* Max error number */ }; /* * Flags defined by the API. */ #define ELF_F_LAYOUT 0x001U /* application will layout the file */ #define ELF_F_DIRTY 0x002U /* a section or ELF file is dirty */ /* ELF(3) API extensions. */ #define ELF_F_ARCHIVE 0x100U /* archive creation */ #define ELF_F_ARCHIVE_SYSV 0x200U /* SYSV style archive */ -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif Elf *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf); int elf_cntl(Elf *_elf, Elf_Cmd _cmd); int elf_end(Elf *_elf); const char *elf_errmsg(int _error); int elf_errno(void); void elf_fill(int _fill); unsigned int elf_flagarhdr(Elf_Arhdr *_arh, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagdata(Elf_Data *_data, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagehdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagelf(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagphdr(Elf *_elf, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagscn(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); unsigned int elf_flagshdr(Elf_Scn *_scn, Elf_Cmd _cmd, unsigned int _flags); Elf_Arhdr *elf_getarhdr(Elf *_elf); Elf_Arsym *elf_getarsym(Elf *_elf, size_t *_ptr); off_t elf_getbase(Elf *_elf); Elf_Data *elf_getdata(Elf_Scn *, Elf_Data *); char *elf_getident(Elf *_elf, size_t *_ptr); int elf_getphdrnum(Elf *_elf, size_t *_dst); int elf_getphnum(Elf *_elf, size_t *_dst); /* Deprecated */ Elf_Scn *elf_getscn(Elf *_elf, size_t _index); int elf_getshdrnum(Elf *_elf, size_t *_dst); int elf_getshnum(Elf *_elf, size_t *_dst); /* Deprecated */ int elf_getshdrstrndx(Elf *_elf, size_t *_dst); int elf_getshstrndx(Elf *_elf, size_t *_dst); /* Deprecated */ unsigned long elf_hash(const char *_name); Elf_Kind elf_kind(Elf *_elf); Elf *elf_memory(char *_image, size_t _size); size_t elf_ndxscn(Elf_Scn *_scn); Elf_Data *elf_newdata(Elf_Scn *_scn); Elf_Scn *elf_newscn(Elf *_elf); Elf_Scn *elf_nextscn(Elf *_elf, Elf_Scn *_scn); Elf_Cmd elf_next(Elf *_elf); Elf *elf_open(int _fd); Elf *elf_openmemory(char *_image, size_t _size); off_t elf_rand(Elf *_elf, off_t _off); Elf_Data *elf_rawdata(Elf_Scn *_scn, Elf_Data *_data); char *elf_rawfile(Elf *_elf, size_t *_size); int elf_setshstrndx(Elf *_elf, size_t _shnum); char *elf_strptr(Elf *_elf, size_t _section, size_t _offset); off_t elf_update(Elf *_elf, Elf_Cmd _cmd); unsigned int elf_version(unsigned int _version); long elf32_checksum(Elf *_elf); size_t elf32_fsize(Elf_Type _type, size_t _count, unsigned int _version); Elf32_Ehdr *elf32_getehdr(Elf *_elf); Elf32_Phdr *elf32_getphdr(Elf *_elf); Elf32_Shdr *elf32_getshdr(Elf_Scn *_scn); Elf32_Ehdr *elf32_newehdr(Elf *_elf); Elf32_Phdr *elf32_newphdr(Elf *_elf, size_t _count); Elf_Data *elf32_xlatetof(Elf_Data *_dst, const Elf_Data *_src, unsigned int _enc); Elf_Data *elf32_xlatetom(Elf_Data *_dst, const Elf_Data *_src, unsigned int _enc); long elf64_checksum(Elf *_elf); size_t elf64_fsize(Elf_Type _type, size_t _count, unsigned int _version); Elf64_Ehdr *elf64_getehdr(Elf *_elf); Elf64_Phdr *elf64_getphdr(Elf *_elf); Elf64_Shdr *elf64_getshdr(Elf_Scn *_scn); Elf64_Ehdr *elf64_newehdr(Elf *_elf); Elf64_Phdr *elf64_newphdr(Elf *_elf, size_t _count); Elf_Data *elf64_xlatetof(Elf_Data *_dst, const Elf_Data *_src, unsigned int _enc); Elf_Data *elf64_xlatetom(Elf_Data *_dst, const Elf_Data *_src, unsigned int _enc); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* _LIBELF_H_ */ Index: head/contrib/elftoolchain/libelf/libelf_align.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_align.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_align.c (revision 280932) @@ -1,137 +1,135 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_align.c 3006 2014-03-22 08:10:07Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_align.c 3174 2015-03-27 17:13:41Z emaste $"); struct align { unsigned int a32; unsigned int a64; }; #ifdef __GNUC__ #define MALIGN(N) { \ .a32 = __alignof__(Elf32_##N), \ .a64 = __alignof__(Elf64_##N) \ } #define MALIGN64(V) { \ .a32 = 0, \ .a64 = __alignof__(Elf64_##V) \ } #define MALIGN_WORD() { \ .a32 = __alignof__(int32_t), \ .a64 = __alignof__(int64_t) \ } #else #error Need the __alignof__ builtin. #endif #define UNSUPPORTED() { \ .a32 = 0, \ .a64 = 0 \ } static struct align malign[ELF_T_NUM] = { [ELF_T_ADDR] = MALIGN(Addr), [ELF_T_BYTE] = { .a32 = 1, .a64 = 1 }, [ELF_T_CAP] = MALIGN(Cap), [ELF_T_DYN] = MALIGN(Dyn), [ELF_T_EHDR] = MALIGN(Ehdr), [ELF_T_HALF] = MALIGN(Half), [ELF_T_LWORD] = MALIGN(Lword), [ELF_T_MOVE] = MALIGN(Move), [ELF_T_MOVEP] = UNSUPPORTED(), [ELF_T_NOTE] = MALIGN(Nhdr), [ELF_T_OFF] = MALIGN(Off), [ELF_T_PHDR] = MALIGN(Phdr), [ELF_T_REL] = MALIGN(Rel), [ELF_T_RELA] = MALIGN(Rela), [ELF_T_SHDR] = MALIGN(Shdr), [ELF_T_SWORD] = MALIGN(Sword), [ELF_T_SXWORD] = MALIGN64(Sxword), [ELF_T_SYM] = MALIGN(Sym), [ELF_T_SYMINFO] = MALIGN(Syminfo), [ELF_T_VDEF] = MALIGN(Verdef), [ELF_T_VNEED] = MALIGN(Verneed), [ELF_T_WORD] = MALIGN(Word), [ELF_T_XWORD] = MALIGN64(Xword), [ELF_T_GNUHASH] = MALIGN_WORD() }; unsigned int _libelf_malign(Elf_Type t, int elfclass) { if (t >= ELF_T_NUM || (int) t < 0) return (0); return (elfclass == ELFCLASS32 ? malign[t].a32 : malign[t].a64); } #define FALIGN(A32,A64) { .a32 = (A32), .a64 = (A64) } static struct align falign[ELF_T_NUM] = { [ELF_T_ADDR] = FALIGN(4,8), [ELF_T_BYTE] = FALIGN(1,1), [ELF_T_CAP] = FALIGN(4,8), [ELF_T_DYN] = FALIGN(4,8), [ELF_T_EHDR] = FALIGN(4,8), [ELF_T_HALF] = FALIGN(2,2), [ELF_T_LWORD] = FALIGN(8,8), [ELF_T_MOVE] = FALIGN(8,8), [ELF_T_MOVEP] = UNSUPPORTED(), [ELF_T_NOTE] = FALIGN(1,1), [ELF_T_OFF] = FALIGN(4,8), [ELF_T_PHDR] = FALIGN(4,8), [ELF_T_REL] = FALIGN(4,8), [ELF_T_RELA] = FALIGN(4,8), [ELF_T_SHDR] = FALIGN(4,8), [ELF_T_SWORD] = FALIGN(4,4), [ELF_T_SXWORD] = FALIGN(0,8), [ELF_T_SYM] = FALIGN(4,8), [ELF_T_SYMINFO] = FALIGN(2,2), [ELF_T_VDEF] = FALIGN(4,4), [ELF_T_VNEED] = FALIGN(4,4), [ELF_T_WORD] = FALIGN(4,4), [ELF_T_XWORD] = FALIGN(0,8), [ELF_T_GNUHASH] = FALIGN(4,8) }; unsigned int _libelf_falign(Elf_Type t, int elfclass) { if (t >= ELF_T_NUM || (int) t < 0) return (0); return (elfclass == ELFCLASS32 ? falign[t].a32 : falign[t].a64); } Index: head/contrib/elftoolchain/libelf/libelf_allocate.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_allocate.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_allocate.c (revision 280932) @@ -1,212 +1,210 @@ /*- * Copyright (c) 2006,2008,2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Internal APIs */ -#include - #include #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_allocate.c 2272 2011-12-03 17:07:31Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_allocate.c 3174 2015-03-27 17:13:41Z emaste $"); Elf * _libelf_allocate_elf(void) { Elf *e; if ((e = malloc(sizeof(*e))) == NULL) { LIBELF_SET_ERROR(RESOURCE, errno); return NULL; } e->e_activations = 1; e->e_hdr.e_rawhdr = NULL; e->e_byteorder = ELFDATANONE; e->e_class = ELFCLASSNONE; e->e_cmd = ELF_C_NULL; e->e_fd = -1; e->e_flags = 0; e->e_kind = ELF_K_NONE; e->e_parent = NULL; e->e_rawfile = NULL; e->e_rawsize = 0; e->e_version = LIBELF_PRIVATE(version); (void) memset(&e->e_u, 0, sizeof(e->e_u)); return (e); } void _libelf_init_elf(Elf *e, Elf_Kind kind) { assert(e != NULL); assert(e->e_kind == ELF_K_NONE); e->e_kind = kind; switch (kind) { case ELF_K_ELF: STAILQ_INIT(&e->e_u.e_elf.e_scn); break; default: break; } } #define FREE(P) do { \ if (P) \ free(P); \ } while (0) Elf * _libelf_release_elf(Elf *e) { Elf_Arhdr *arh; switch (e->e_kind) { case ELF_K_AR: FREE(e->e_u.e_ar.e_symtab); break; case ELF_K_ELF: switch (e->e_class) { case ELFCLASS32: FREE(e->e_u.e_elf.e_ehdr.e_ehdr32); FREE(e->e_u.e_elf.e_phdr.e_phdr32); break; case ELFCLASS64: FREE(e->e_u.e_elf.e_ehdr.e_ehdr64); FREE(e->e_u.e_elf.e_phdr.e_phdr64); break; } assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); if (e->e_flags & LIBELF_F_AR_HEADER) { arh = e->e_hdr.e_arhdr; FREE(arh->ar_name); FREE(arh->ar_rawname); free(arh); } break; default: break; } free(e); return (NULL); } struct _Libelf_Data * _libelf_allocate_data(Elf_Scn *s) { struct _Libelf_Data *d; if ((d = calloc((size_t) 1, sizeof(*d))) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } d->d_scn = s; return (d); } struct _Libelf_Data * _libelf_release_data(struct _Libelf_Data *d) { if (d->d_flags & LIBELF_F_DATA_MALLOCED) free(d->d_data.d_buf); free(d); return (NULL); } Elf_Scn * _libelf_allocate_scn(Elf *e, size_t ndx) { Elf_Scn *s; if ((s = calloc((size_t) 1, sizeof(Elf_Scn))) == NULL) { LIBELF_SET_ERROR(RESOURCE, errno); return (NULL); } s->s_elf = e; s->s_ndx = ndx; STAILQ_INIT(&s->s_data); STAILQ_INIT(&s->s_rawdata); STAILQ_INSERT_TAIL(&e->e_u.e_elf.e_scn, s, s_next); return (s); } Elf_Scn * _libelf_release_scn(Elf_Scn *s) { Elf *e; struct _Libelf_Data *d, *td; assert(s != NULL); STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) { STAILQ_REMOVE(&s->s_data, d, _Libelf_Data, d_next); d = _libelf_release_data(d); } STAILQ_FOREACH_SAFE(d, &s->s_rawdata, d_next, td) { assert((d->d_flags & LIBELF_F_DATA_MALLOCED) == 0); STAILQ_REMOVE(&s->s_rawdata, d, _Libelf_Data, d_next); d = _libelf_release_data(d); } e = s->s_elf; assert(e != NULL); STAILQ_REMOVE(&e->e_u.e_elf.e_scn, s, _Elf_Scn, s_next); free(s); return (NULL); } Index: head/contrib/elftoolchain/libelf/libelf_ar.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_ar.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_ar.c (revision 280932) @@ -1,468 +1,466 @@ /*- * Copyright (c) 2006,2008,2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include #include "_libelf.h" #include "_libelf_ar.h" -ELFTC_VCSID("$Id: libelf_ar.c 3013 2014-03-23 06:16:59Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_ar.c 3174 2015-03-27 17:13:41Z emaste $"); #define LIBELF_NALLOC_SIZE 16 /* * `ar' archive handling. * * `ar' archives start with signature `ARMAG'. Each archive member is * preceded by a header containing meta-data for the member. This * header is described in (struct ar_hdr). The header always * starts on an even address. File data is padded with "\n" * characters to keep this invariant. * * Special considerations for `ar' archives: * * There are two variants of the `ar' archive format: traditional BSD * and SVR4. These differ in the way long file names are treated, and * in the layout of the archive symbol table. * * The `ar' header only has space for a 16 character file name. * * In the SVR4 format, file names are terminated with a '/', so this * effectively leaves 15 characters for the actual file name. Longer * file names stored in a separate 'string table' and referenced * indirectly from the name field. The string table itself appears as * an archive member with name "// ". An `indirect' file name in an * `ar' header matches the pattern "/[0-9]*". The digits form a * decimal number that corresponds to a byte offset into the string * table where the actual file name of the object starts. Strings in * the string table are padded to start on even addresses. * * In the BSD format, file names can be upto 16 characters. File * names shorter than 16 characters are padded to 16 characters using * (ASCII) space characters. File names with embedded spaces and file * names longer than 16 characters are stored immediately after the * archive header and the name field set to a special indirect name * matching the pattern "#1/[0-9]+". The digits form a decimal number * that corresponds to the actual length of the file name following * the archive header. The content of the archive member immediately * follows the file name, and the size field of the archive member * holds the sum of the sizes of the member and of the appended file * name. * * Archives may also have a symbol table (see ranlib(1)), mapping * program symbols to object files inside the archive. * * In the SVR4 format, a symbol table uses a file name of "/ " in its * archive header. The symbol table is structured as: * - a 4-byte count of entries stored as a binary value, MSB first * - 'n' 4-byte offsets, stored as binary values, MSB first * - 'n' NUL-terminated strings, for ELF symbol names, stored unpadded. * * In the BSD format, the symbol table uses a file name of "__.SYMDEF". * It is structured as two parts: * - The first part is an array of "ranlib" structures preceded by * the size of the array in bytes. Each "ranlib" structure * describes one symbol. Each structure contains an offset into * the string table for the symbol name, and a file offset into the * archive for the member defining the symbol. * - The second part is a string table containing NUL-terminated * strings, preceded by the size of the string table in bytes. * * If the symbol table and string table are is present in an archive * they must be the very first objects and in that order. */ /* * Retrieve an archive header descriptor. */ Elf_Arhdr * _libelf_ar_gethdr(Elf *e) { Elf *parent; Elf_Arhdr *eh; char *namelen; size_t n, nlen; struct ar_hdr *arh; if ((parent = e->e_parent) == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert((e->e_flags & LIBELF_F_AR_HEADER) == 0); arh = (struct ar_hdr *) (uintptr_t) e->e_hdr.e_rawhdr; assert((uintptr_t) arh >= (uintptr_t) parent->e_rawfile + SARMAG); assert((uintptr_t) arh <= (uintptr_t) parent->e_rawfile + parent->e_rawsize - sizeof(struct ar_hdr)); if ((eh = malloc(sizeof(Elf_Arhdr))) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } e->e_hdr.e_arhdr = eh; e->e_flags |= LIBELF_F_AR_HEADER; eh->ar_name = eh->ar_rawname = NULL; if ((eh->ar_name = _libelf_ar_get_translated_name(arh, parent)) == NULL) goto error; if (_libelf_ar_get_number(arh->ar_uid, sizeof(arh->ar_uid), 10, &n) == 0) goto error; eh->ar_uid = (uid_t) n; if (_libelf_ar_get_number(arh->ar_gid, sizeof(arh->ar_gid), 10, &n) == 0) goto error; eh->ar_gid = (gid_t) n; if (_libelf_ar_get_number(arh->ar_mode, sizeof(arh->ar_mode), 8, &n) == 0) goto error; eh->ar_mode = (mode_t) n; if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &n) == 0) goto error; /* * Get the true size of the member if extended naming is being used. */ if (IS_EXTENDED_BSD_NAME(arh->ar_name)) { namelen = arh->ar_name + LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE; if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) - LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nlen) == 0) goto error; n -= nlen; } eh->ar_size = n; if ((eh->ar_rawname = _libelf_ar_get_raw_name(arh)) == NULL) goto error; eh->ar_flags = 0; return (eh); error: if (eh) { if (eh->ar_name) free(eh->ar_name); if (eh->ar_rawname) free(eh->ar_rawname); free(eh); } e->e_flags &= ~LIBELF_F_AR_HEADER; e->e_hdr.e_rawhdr = (unsigned char *) arh; return (NULL); } Elf * _libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf) { Elf *e; off_t next; size_t nsz, sz; struct ar_hdr *arh; char *member, *namelen; assert(elf->e_kind == ELF_K_AR); next = elf->e_u.e_ar.e_next; /* * `next' is only set to zero by elf_next() when the last * member of an archive is processed. */ if (next == (off_t) 0) return (NULL); assert((next & 1) == 0); arh = (struct ar_hdr *) (elf->e_rawfile + next); /* * Retrieve the size of the member. */ if (_libelf_ar_get_number(arh->ar_size, sizeof(arh->ar_size), 10, &sz) == 0) { LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } /* * Adjust the size field for members in BSD archives using * extended naming. */ if (IS_EXTENDED_BSD_NAME(arh->ar_name)) { namelen = arh->ar_name + LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE; if (_libelf_ar_get_number(namelen, sizeof(arh->ar_name) - LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &nsz) == 0) { LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } member = (char *) (arh + 1) + nsz; sz -= nsz; } else member = (char *) (arh + 1); if ((e = elf_memory(member, sz)) == NULL) return (NULL); e->e_fd = fd; e->e_cmd = c; e->e_hdr.e_rawhdr = (unsigned char *) arh; elf->e_u.e_ar.e_nchildren++; e->e_parent = elf; return (e); } /* * A BSD-style ar(1) symbol table has the following layout: * * - A count of bytes used by the following array of 'ranlib' * structures, stored as a 'long'. * - An array of 'ranlib' structures. Each array element is * two 'long's in size. * - A count of bytes used for the following symbol table. * - The symbol table itself. */ /* * A helper macro to read in a 'long' value from the archive. * * We use memcpy() since the source pointer may be misaligned with * respect to the natural alignment for a C 'long'. */ #define GET_LONG(P, V)do { \ memcpy(&(V), (P), sizeof(long)); \ (P) += sizeof(long); \ } while (0) Elf_Arsym * _libelf_ar_process_bsd_symtab(Elf *e, size_t *count) { Elf_Arsym *symtab, *sym; unsigned int n, nentries; unsigned char *end, *p, *p0, *s, *s0; const size_t entrysize = 2 * sizeof(long); long arraysize, fileoffset, stroffset, strtabsize; assert(e != NULL); assert(count != NULL); assert(e->e_u.e_ar.e_symtab == NULL); symtab = NULL; /* * The BSD symbol table always contains the count fields even * if there are no entries in it. */ if (e->e_u.e_ar.e_rawsymtabsz < 2 * sizeof(long)) goto symtaberror; p = p0 = (unsigned char *) e->e_u.e_ar.e_rawsymtab; end = p0 + e->e_u.e_ar.e_rawsymtabsz; /* * Retrieve the size of the array of ranlib descriptors and * check it for validity. */ GET_LONG(p, arraysize); if (arraysize < 0 || p0 + arraysize >= end || ((size_t) arraysize % entrysize != 0)) goto symtaberror; /* * Check the value of the string table size. */ s = p + arraysize; GET_LONG(s, strtabsize); s0 = s; /* Start of string table. */ if (strtabsize < 0 || s0 + strtabsize > end) goto symtaberror; nentries = (size_t) arraysize / entrysize; /* * Allocate space for the returned Elf_Arsym array. */ if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries + 1))) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } /* Read in symbol table entries. */ for (n = 0, sym = symtab; n < nentries; n++, sym++) { GET_LONG(p, stroffset); GET_LONG(p, fileoffset); if (stroffset < 0 || fileoffset < 0 || (size_t) fileoffset >= e->e_rawsize) goto symtaberror; s = s0 + stroffset; if (s >= end) goto symtaberror; sym->as_off = (off_t) fileoffset; sym->as_hash = elf_hash((char *) s); sym->as_name = (char *) s; } /* Fill up the sentinel entry. */ sym->as_name = NULL; sym->as_hash = ~0UL; sym->as_off = (off_t) 0; /* Remember the processed symbol table. */ e->e_u.e_ar.e_symtab = symtab; *count = e->e_u.e_ar.e_symtabsz = nentries + 1; return (symtab); symtaberror: if (symtab) free(symtab); LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } /* * An SVR4-style ar(1) symbol table has the following layout: * * - The first 4 bytes are a binary count of the number of entries in the * symbol table, stored MSB-first. * - Then there are 'n' 4-byte binary offsets, also stored MSB first. * - Following this, there are 'n' null-terminated strings. */ #define GET_WORD(P, V) do { \ (V) = 0; \ (V) = (P)[0]; (V) <<= 8; \ (V) += (P)[1]; (V) <<= 8; \ (V) += (P)[2]; (V) <<= 8; \ (V) += (P)[3]; \ } while (0) #define INTSZ 4 Elf_Arsym * _libelf_ar_process_svr4_symtab(Elf *e, size_t *count) { uint32_t off; size_t n, nentries; Elf_Arsym *symtab, *sym; unsigned char *p, *s, *end; assert(e != NULL); assert(count != NULL); assert(e->e_u.e_ar.e_symtab == NULL); symtab = NULL; if (e->e_u.e_ar.e_rawsymtabsz < INTSZ) goto symtaberror; p = (unsigned char *) e->e_u.e_ar.e_rawsymtab; end = p + e->e_u.e_ar.e_rawsymtabsz; GET_WORD(p, nentries); p += INTSZ; if (nentries == 0 || p + nentries * INTSZ >= end) goto symtaberror; /* Allocate space for a nentries + a sentinel. */ if ((symtab = malloc(sizeof(Elf_Arsym) * (nentries+1))) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } s = p + (nentries * INTSZ); /* start of the string table. */ for (n = nentries, sym = symtab; n > 0; n--) { if (s >= end) goto symtaberror; GET_WORD(p, off); if (off >= e->e_rawsize) goto symtaberror; sym->as_off = (off_t) off; sym->as_hash = elf_hash((char *) s); sym->as_name = (char *) s; p += INTSZ; sym++; for (; s < end && *s++ != '\0';) /* skip to next string */ ; } /* Fill up the sentinel entry. */ sym->as_name = NULL; sym->as_hash = ~0UL; sym->as_off = (off_t) 0; *count = e->e_u.e_ar.e_symtabsz = nentries + 1; e->e_u.e_ar.e_symtab = symtab; return (symtab); symtaberror: if (symtab) free(symtab); LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } Index: head/contrib/elftoolchain/libelf/libelf_ar_util.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_ar_util.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_ar_util.c (revision 280932) @@ -1,362 +1,360 @@ /*- * Copyright (c) 2006,2009,2010 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" #include "_libelf_ar.h" -ELFTC_VCSID("$Id: libelf_ar_util.c 3157 2015-02-15 21:42:02Z emaste $"); +ELFTC_VCSID("$Id: libelf_ar_util.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Convert a string bounded by `start' and `start+sz' (exclusive) to a * number in the specified base. */ int _libelf_ar_get_number(const char *src, size_t sz, unsigned int base, size_t *ret) { size_t r; unsigned int c, v; const unsigned char *e, *s; assert(base <= 10); s = (const unsigned char *) src; e = s + sz; /* skip leading blanks */ for (;s < e && (c = *s) == ' '; s++) ; r = 0L; for (;s < e; s++) { if ((c = *s) == ' ') break; if (c < '0' || c > '9') return (0); v = c - '0'; if (v >= base) /* Illegal digit. */ break; r *= base; r += v; } *ret = r; return (1); } /* * Return the translated name for an archive member. */ char * _libelf_ar_get_translated_name(const struct ar_hdr *arh, Elf *ar) { char *s; unsigned char c; size_t len, offset; const unsigned char *buf, *p, *q, *r; const size_t bufsize = sizeof(arh->ar_name); assert(arh != NULL); assert(ar->e_kind == ELF_K_AR); assert((const unsigned char *) arh >= ar->e_rawfile && (const unsigned char *) arh < ar->e_rawfile + ar->e_rawsize); buf = (const unsigned char *) arh->ar_name; /* * Check for extended naming. * * If the name matches the pattern "^/[0-9]+", it is an * SVR4-style extended name. If the name matches the pattern * "#1/[0-9]+", the entry uses BSD style extended naming. */ if (buf[0] == '/' && (c = buf[1]) >= '0' && c <= '9') { /* * The value in field ar_name is a decimal offset into * the archive string table where the actual name * resides. */ if (_libelf_ar_get_number((const char *) (buf + 1), bufsize - 1, 10, &offset) == 0) { LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } if (offset > ar->e_u.e_ar.e_rawstrtabsz) { LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } p = q = ar->e_u.e_ar.e_rawstrtab + offset; r = ar->e_u.e_ar.e_rawstrtab + ar->e_u.e_ar.e_rawstrtabsz; for (; p < r && *p != '/'; p++) ; len = (size_t) (p - q + 1); /* space for the trailing NUL */ if ((s = malloc(len)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } (void) strncpy(s, (const char *) q, len - 1); s[len - 1] = '\0'; return (s); } else if (IS_EXTENDED_BSD_NAME(buf)) { r = buf + LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE; if (_libelf_ar_get_number((const char *) r, bufsize - LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE, 10, &len) == 0) { LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } /* * Allocate space for the file name plus a * trailing NUL. */ if ((s = malloc(len + 1)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } /* * The file name follows the archive header. */ q = (const unsigned char *) (arh + 1); (void) strncpy(s, (const char *) q, len); s[len] = '\0'; return (s); } /* * A 'normal' name. * * Skip back over trailing blanks from the end of the field. * In the SVR4 format, a '/' is used as a terminator for * non-special names. */ for (q = buf + bufsize - 1; q >= buf && *q == ' '; --q) ; if (q >= buf) { if (*q == '/') { /* * SVR4 style names: ignore the trailing * character '/', but only if the name is not * one of the special names "/" and "//". */ if (q > buf + 1 || (q == (buf + 1) && *buf != '/')) q--; } len = (size_t) (q - buf + 2); /* Space for a trailing NUL. */ } else { /* The buffer only had blanks. */ buf = (const unsigned char *) ""; len = 1; } if ((s = malloc(len)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } (void) strncpy(s, (const char *) buf, len - 1); s[len - 1] = '\0'; return (s); } /* * Return the raw name for an archive member, inclusive of any * formatting characters. */ char * _libelf_ar_get_raw_name(const struct ar_hdr *arh) { char *rawname; const size_t namesz = sizeof(arh->ar_name); if ((rawname = malloc(namesz + 1)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } (void) strncpy(rawname, arh->ar_name, namesz); rawname[namesz] = '\0'; return (rawname); } /* * Open an 'ar' archive. */ Elf * _libelf_ar_open(Elf *e, int reporterror) { size_t sz; int scanahead; struct ar_hdr arh; unsigned char *s, *end; _libelf_init_elf(e, ELF_K_AR); e->e_u.e_ar.e_nchildren = 0; e->e_u.e_ar.e_next = (off_t) -1; /* * Look for special members. */ s = e->e_rawfile + SARMAG; end = e->e_rawfile + e->e_rawsize; assert(e->e_rawsize > 0); /* * We use heuristics to determine the flavor of the archive we * are examining. * * SVR4 flavor archives use the name "/ " and "// " for * special members. * * In BSD flavor archives the symbol table, if present, is the * first archive with name "__.SYMDEF". */ #define READ_AR_HEADER(S, ARH, SZ, END) \ do { \ if ((S) + sizeof((ARH)) > (END)) \ goto error; \ (void) memcpy(&(ARH), (S), sizeof((ARH))); \ if ((ARH).ar_fmag[0] != '`' || (ARH).ar_fmag[1] != '\n') \ goto error; \ if (_libelf_ar_get_number((char *) (ARH).ar_size, \ sizeof((ARH).ar_size), 10, &(SZ)) == 0) \ goto error; \ } while (0) READ_AR_HEADER(s, arh, sz, end); /* * Handle special archive members for the SVR4 format. */ if (arh.ar_name[0] == '/') { if (sz == 0) goto error; e->e_flags |= LIBELF_F_AR_VARIANT_SVR4; scanahead = 0; /* * The symbol table (file name "/ ") always comes before the * string table (file name "// "). */ if (arh.ar_name[1] == ' ') { /* "/ " => symbol table. */ scanahead = 1; /* The string table to follow. */ s += sizeof(arh); e->e_u.e_ar.e_rawsymtab = s; e->e_u.e_ar.e_rawsymtabsz = sz; sz = LIBELF_ADJUST_AR_SIZE(sz); s += sz; } else if (arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') { /* "// " => string table for long file names. */ s += sizeof(arh); e->e_u.e_ar.e_rawstrtab = s; e->e_u.e_ar.e_rawstrtabsz = sz; sz = LIBELF_ADJUST_AR_SIZE(sz); s += sz; } /* * If the string table hasn't been seen yet, look for * it in the next member. */ if (scanahead) { READ_AR_HEADER(s, arh, sz, end); /* "// " => string table for long file names. */ if (arh.ar_name[0] == '/' && arh.ar_name[1] == '/' && arh.ar_name[2] == ' ') { s += sizeof(arh); e->e_u.e_ar.e_rawstrtab = s; e->e_u.e_ar.e_rawstrtabsz = sz; sz = LIBELF_ADJUST_AR_SIZE(sz); s += sz; } } } else if (strncmp(arh.ar_name, LIBELF_AR_BSD_SYMTAB_NAME, sizeof(LIBELF_AR_BSD_SYMTAB_NAME) - 1) == 0) { /* * BSD style archive symbol table. */ s += sizeof(arh); e->e_u.e_ar.e_rawsymtab = s; e->e_u.e_ar.e_rawsymtabsz = sz; sz = LIBELF_ADJUST_AR_SIZE(sz); s += sz; } /* * Update the 'next' offset, so that a subsequent elf_begin() * works as expected. */ e->e_u.e_ar.e_next = (off_t) (s - e->e_rawfile); return (e); error: if (!reporterror) { e->e_kind = ELF_K_NONE; return (e); } LIBELF_SET_ERROR(ARCHIVE, 0); return (NULL); } Index: head/contrib/elftoolchain/libelf/libelf_checksum.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_checksum.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_checksum.c (revision 280932) @@ -1,100 +1,98 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_checksum.c 3003 2014-03-22 07:43:10Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_checksum.c 3174 2015-03-27 17:13:41Z emaste $"); static unsigned long _libelf_sum(unsigned long c, const unsigned char *s, size_t size) { if (s == NULL || size == 0) return (c); while (size--) c += *s++; return (c); } long _libelf_checksum(Elf *e, int elfclass) { size_t shn; Elf_Scn *scn; Elf_Data *d; unsigned long checksum; GElf_Ehdr eh; GElf_Shdr shdr; if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (0L); } if (e->e_class != elfclass) { LIBELF_SET_ERROR(CLASS, 0); return (0L); } if (gelf_getehdr(e, &eh) == NULL) return (0); /* * Iterate over all sections in the ELF file, computing the * checksum along the way. * * The first section is always SHN_UNDEF and can be skipped. * Non-allocatable sections are skipped, as are sections that * could be affected by utilities such as strip(1). */ checksum = 0; for (shn = 1; shn < e->e_u.e_elf.e_nscn; shn++) { if ((scn = elf_getscn(e, shn)) == NULL) return (0); if (gelf_getshdr(scn, &shdr) == NULL) return (0); if ((shdr.sh_flags & SHF_ALLOC) == 0 || shdr.sh_type == SHT_DYNAMIC || shdr.sh_type == SHT_DYNSYM) continue; d = NULL; while ((d = elf_rawdata(scn, d)) != NULL) checksum = _libelf_sum(checksum, (unsigned char *) d->d_buf, (size_t) d->d_size); } /* * Return a 16-bit checksum compatible with Solaris. */ return (long) (((checksum >> 16) & 0xFFFFUL) + (checksum & 0xFFFFUL)); } Index: head/contrib/elftoolchain/libelf/libelf_convert.m4 =================================================================== --- head/contrib/elftoolchain/libelf/libelf_convert.m4 (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_convert.m4 (revision 280932) @@ -1,1089 +1,1087 @@ /*- * Copyright (c) 2006-2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_convert.m4 3158 2015-02-15 21:42:07Z emaste $"); +ELFTC_VCSID("$Id: libelf_convert.m4 3174 2015-03-27 17:13:41Z emaste $"); /* WARNING: GENERATED FROM __file__. */ divert(-1) # Generate conversion routines for converting between in-memory and # file representations of Elf data structures. # # These conversions use the type information defined in `elf_types.m4'. include(SRCDIR`/elf_types.m4') # For the purposes of generating conversion code, ELF types may be # classified according to the following characteristics: # # 1. Whether the ELF type can be directly mapped to an integral C # language type. For example, the ELF_T_WORD type maps directly to # a 'uint32_t', but ELF_T_GNUHASH lacks a matching C type. # # 2. Whether the type has word size dependent variants. For example, # ELT_T_EHDR is represented using C types Elf32_Ehdr and El64_Ehdr, # and the ELF_T_ADDR and ELF_T_OFF types have integral C types that # can be 32- or 64- bit wide. # # 3. Whether the ELF types has a fixed representation or not. For # example, the ELF_T_SYM type has a fixed size file representation, # some types like ELF_T_NOTE and ELF_T_GNUHASH use a variable size # representation. # # We use m4 macros to generate conversion code for ELF types that have # a fixed size representation. Conversion functions for the remaining # types are coded by hand. # #* Handling File and Memory Representations # # `In-memory' representations of an Elf data structure use natural # alignments and native byte ordering. This allows pointer arithmetic # and casting to work as expected. On the other hand, the `file' # representation of an ELF data structure could possibly be packed # tighter than its `in-memory' representation, and could be of a # differing byte order. Reading ELF objects that are members of `ar' # archives present an additional complication: `ar' pads file data to # even addresses, so file data structures in an archive member # residing inside an `ar' archive could be at misaligned memory # addresses when brought into memory. # # In summary, casting the `char *' pointers that point to memory # representations (i.e., source pointers for the *_tof() functions and # the destination pointers for the *_tom() functions), is safe, as # these pointers should be correctly aligned for the memory type # already. However, pointers to file representations have to be # treated as being potentially unaligned and no casting can be done. # NOCVT(TYPE) -- Do not generate the cvt[] structure entry for TYPE define(`NOCVT',`define(`NOCVT_'$1,1)') # NOFUNC(TYPE) -- Do not generate a conversion function for TYPE define(`NOFUNC',`define(`NOFUNC_'$1,1)') # IGNORE(TYPE) -- Completely ignore the type. define(`IGNORE',`NOCVT($1)NOFUNC($1)') # Mark ELF types that should not be processed by the M4 macros below. # Types for which we use functions with non-standard names. IGNORE(`BYTE') # Uses a wrapper around memcpy(). IGNORE(`NOTE') # Not a fixed size type. # Types for which we supply hand-coded functions. NOFUNC(`GNUHASH') # A type with complex internal structure. NOFUNC(`VDEF') # See MAKE_VERSION_CONVERTERS below. NOFUNC(`VNEED') # .. # Unimplemented types. IGNORE(`MOVEP') # ELF types that don't exist in a 32-bit world. NOFUNC(`XWORD32') NOFUNC(`SXWORD32') # `Primitive' ELF types are those that are an alias for an integral # type. As they have no internal structure, they can be copied using # a `memcpy()', and byteswapped in straightforward way. # # Mark all ELF types that directly map to integral C types. define(`PRIM_ADDR', 1) define(`PRIM_BYTE', 1) define(`PRIM_HALF', 1) define(`PRIM_LWORD', 1) define(`PRIM_OFF', 1) define(`PRIM_SWORD', 1) define(`PRIM_SXWORD', 1) define(`PRIM_WORD', 1) define(`PRIM_XWORD', 1) # Note the primitive types that are size-dependent. define(`SIZEDEP_ADDR', 1) define(`SIZEDEP_OFF', 1) # Generate conversion functions for primitive types. # # Macro use: MAKEPRIMFUNCS(ELFTYPE,CTYPE,TYPESIZE,SYMSIZE) # `$1': Name of the ELF type. # `$2': C structure name suffix. # `$3': ELF class specifier for types, one of [`32', `64']. # `$4': Additional ELF class specifier, one of [`', `32', `64']. # # Generates a pair of conversion functions. define(`MAKEPRIMFUNCS',` static int _libelf_cvt_$1$4_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$3_$2 t, *s = (Elf$3_$2 *) (uintptr_t) src; size_t c; (void) dsz; if (!byteswap) { (void) memcpy(dst, src, count * sizeof(*s)); return (1); } for (c = 0; c < count; c++) { t = *s++; SWAP_$1$4(t); WRITE_$1$4(dst,t); } return (1); } static int _libelf_cvt_$1$4_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$3_$2 t, *d = (Elf$3_$2 *) (uintptr_t) dst; size_t c; if (dsz < count * sizeof(Elf$3_$2)) return (0); if (!byteswap) { (void) memcpy(dst, src, count * sizeof(*d)); return (1); } for (c = 0; c < count; c++) { READ_$1$4(src,t); SWAP_$1$4(t); *d++ = t; } return (1); } ') # # Handling composite ELF types # # SWAP_FIELD(FIELDNAME,ELFTYPE) -- Generate code to swap one field. define(`SWAP_FIELD', `ifdef(`SIZEDEP_'$2, `SWAP_$2'SZ()`(t.$1); ', `SWAP_$2(t.$1); ')') # SWAP_MEMBERS(STRUCT) -- Iterate over a structure definition. define(`SWAP_MEMBERS', `ifelse($#,1,`/**/', `SWAP_FIELD($1)SWAP_MEMBERS(shift($@))')') # SWAP_STRUCT(CTYPE,SIZE) -- Generate code to swap an ELF structure. define(`SWAP_STRUCT', `pushdef(`SZ',$2)/* Swap an Elf$2_$1 */ SWAP_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') # WRITE_FIELD(ELFTYPE,FIELDNAME) -- Generate code to write one field. define(`WRITE_FIELD', `ifdef(`SIZEDEP_'$2, `WRITE_$2'SZ()`(dst,t.$1); ', `WRITE_$2(dst,t.$1); ')') # WRITE_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. define(`WRITE_MEMBERS', `ifelse($#,1,`/**/', `WRITE_FIELD($1)WRITE_MEMBERS(shift($@))')') # WRITE_STRUCT(CTYPE,SIZE) -- Generate code to write out an ELF structure. define(`WRITE_STRUCT', `pushdef(`SZ',$2)/* Write an Elf$2_$1 */ WRITE_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') # READ_FIELD(ELFTYPE,CTYPE) -- Generate code to read one field. define(`READ_FIELD', `ifdef(`SIZEDEP_'$2, `READ_$2'SZ()`(s,t.$1); ', `READ_$2(s,t.$1); ')') # READ_MEMBERS(ELFTYPELIST) -- Iterate over a structure definition. define(`READ_MEMBERS', `ifelse($#,1,`/**/', `READ_FIELD($1)READ_MEMBERS(shift($@))')') # READ_STRUCT(CTYPE,SIZE) -- Generate code to read an ELF structure. define(`READ_STRUCT', `pushdef(`SZ',$2)/* Read an Elf$2_$1 */ READ_MEMBERS(Elf$2_$1_DEF)popdef(`SZ')') # MAKECOMPFUNCS -- Generate converters for composite ELF structures. # # When converting data to file representation, the source pointer will # be naturally aligned for a data structure's in-memory # representation. When converting data to memory, the destination # pointer will be similarly aligned. # # For in-place conversions, when converting to file representations, # the source buffer is large enough to hold `file' data. When # converting from file to memory, we need to be careful to work # `backwards', to avoid overwriting unconverted data. # # Macro use: # `$1': Name of the ELF type. # `$2': C structure name suffix. # `$3': ELF class specifier, one of [`', `32', `64'] define(`MAKECOMPFUNCS', `ifdef(`NOFUNC_'$1$3,`',` static int _libelf_cvt_$1$3_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$3_$2 t, *s; size_t c; (void) dsz; s = (Elf$3_$2 *) (uintptr_t) src; for (c = 0; c < count; c++) { t = *s++; if (byteswap) { SWAP_STRUCT($2,$3) } WRITE_STRUCT($2,$3) } return (1); } static int _libelf_cvt_$1$3_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$3_$2 t, *d; unsigned char *s,*s0; size_t fsz; fsz = elf$3_fsize(ELF_T_$1, (size_t) 1, EV_CURRENT); d = ((Elf$3_$2 *) (uintptr_t) dst) + (count - 1); s0 = src + (count - 1) * fsz; if (dsz < count * sizeof(Elf$3_$2)) return (0); while (count--) { s = s0; READ_STRUCT($2,$3) if (byteswap) { SWAP_STRUCT($2,$3) } *d-- = t; s0 -= fsz; } return (1); } ')') # MAKE_TYPE_CONVERTER(ELFTYPE,CTYPE) # # Make type convertor functions from the type definition # of the ELF type: # - Skip convertors marked as `NOFUNC'. # - Invoke `MAKEPRIMFUNCS' or `MAKECOMPFUNCS' as appropriate. define(`MAKE_TYPE_CONVERTER', `ifdef(`NOFUNC_'$1,`', `ifdef(`PRIM_'$1, `ifdef(`SIZEDEP_'$1, `MAKEPRIMFUNCS($1,$2,32,32)dnl MAKEPRIMFUNCS($1,$2,64,64)', `MAKEPRIMFUNCS($1,$2,64)')', `MAKECOMPFUNCS($1,$2,32)dnl MAKECOMPFUNCS($1,$2,64)')')') # MAKE_TYPE_CONVERTERS(ELFTYPELIST) -- Generate conversion functions. define(`MAKE_TYPE_CONVERTERS', `ifelse($#,1,`', `MAKE_TYPE_CONVERTER($1)MAKE_TYPE_CONVERTERS(shift($@))')') # # Macros to generate entries for the table of convertors. # # CONV(ELFTYPE,SIZE,DIRECTION) # # Generate the name of a convertor function. define(`CONV', `ifdef(`NOFUNC_'$1$2, `.$3$2 = NULL', `ifdef(`PRIM_'$1, `ifdef(`SIZEDEP_'$1, `.$3$2 = _libelf_cvt_$1$2_$3', `.$3$2 = _libelf_cvt_$1_$3')', `.$3$2 = _libelf_cvt_$1$2_$3')')') # CONVERTER_NAME(ELFTYPE) # # Generate the contents of one `struct cvt' instance. define(`CONVERTER_NAME', `ifdef(`NOCVT_'$1,`', ` [ELF_T_$1] = { CONV($1,32,tof), CONV($1,32,tom), CONV($1,64,tof), CONV($1,64,tom) }, ')') # CONVERTER_NAMES(ELFTYPELIST) # # Generate the `struct cvt[]' array. define(`CONVERTER_NAMES', `ifelse($#,1,`', `CONVERTER_NAME($1)CONVERTER_NAMES(shift($@))')') # # Handling ELF version sections. # # _FSZ(FIELD,BASETYPE) - return the file size for a field. define(`_FSZ', `ifelse($2,`HALF',2, $2,`WORD',4)') # FSZ(STRUCT) - determine the file size of a structure. define(`FSZ', `ifelse($#,1,0, `eval(_FSZ($1) + FSZ(shift($@)))')') # MAKE_VERSION_CONVERTERS(TYPE,BASE,AUX,PFX) -- Generate conversion # functions for versioning structures. define(`MAKE_VERSION_CONVERTERS', `MAKE_VERSION_CONVERTER($1,$2,$3,$4,32) MAKE_VERSION_CONVERTER($1,$2,$3,$4,64)') # MAKE_VERSION_CONVERTOR(TYPE,CBASE,CAUX,PFX,SIZE) -- Generate a # conversion function. define(`MAKE_VERSION_CONVERTER',` static int _libelf_cvt_$1$5_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$5_$2 t; Elf$5_$3 a; const size_t verfsz = FSZ(Elf$5_$2_DEF); const size_t auxfsz = FSZ(Elf$5_$3_DEF); const size_t vermsz = sizeof(Elf$5_$2); const size_t auxmsz = sizeof(Elf$5_$3); unsigned char * const dstend = dst + dsz; unsigned char * const srcend = src + count; unsigned char *dtmp, *dstaux, *srcaux; Elf$5_Word aux, anext, cnt, vnext; for (dtmp = dst, vnext = ~0U; vnext != 0 && dtmp + verfsz <= dstend && src + vermsz <= srcend; dtmp += vnext, src += vnext) { /* Read in an Elf$5_$2 structure. */ t = *((Elf$5_$2 *) (uintptr_t) src); aux = t.$4_aux; cnt = t.$4_cnt; vnext = t.$4_next; if (byteswap) { SWAP_STRUCT($2, $5) } dst = dtmp; WRITE_STRUCT($2, $5) if (aux < verfsz) return (0); /* Process AUX entries. */ for (anext = ~0U, dstaux = dtmp + aux, srcaux = src + aux; cnt != 0 && anext != 0 && dstaux + auxfsz <= dstend && srcaux + auxmsz <= srcend; dstaux += anext, srcaux += anext, cnt--) { /* Read in an Elf$5_$3 structure. */ a = *((Elf$5_$3 *) (uintptr_t) srcaux); anext = a.$4a_next; if (byteswap) { pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') } dst = dstaux; pushdef(`t',`a')WRITE_STRUCT($3, $5)popdef(`t') } if (anext || cnt) return (0); } if (vnext) return (0); return (1); } static int _libelf_cvt_$1$5_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { Elf$5_$2 t, *dp; Elf$5_$3 a, *ap; const size_t verfsz = FSZ(Elf$5_$2_DEF); const size_t auxfsz = FSZ(Elf$5_$3_DEF); const size_t vermsz = sizeof(Elf$5_$2); const size_t auxmsz = sizeof(Elf$5_$3); unsigned char * const dstend = dst + dsz; unsigned char * const srcend = src + count; unsigned char *dstaux, *s, *srcaux, *stmp; Elf$5_Word aux, anext, cnt, vnext; for (stmp = src, vnext = ~0U; vnext != 0 && stmp + verfsz <= srcend && dst + vermsz <= dstend; stmp += vnext, dst += vnext) { /* Read in a $1 structure. */ s = stmp; READ_STRUCT($2, $5) if (byteswap) { SWAP_STRUCT($2, $5) } dp = (Elf$5_$2 *) (uintptr_t) dst; *dp = t; aux = t.$4_aux; cnt = t.$4_cnt; vnext = t.$4_next; if (aux < vermsz) return (0); /* Process AUX entries. */ for (anext = ~0U, dstaux = dst + aux, srcaux = stmp + aux; cnt != 0 && anext != 0 && dstaux + auxmsz <= dstend && srcaux + auxfsz <= srcend; dstaux += anext, srcaux += anext, cnt--) { s = srcaux; pushdef(`t',`a')READ_STRUCT($3, $5)popdef(`t') if (byteswap) { pushdef(`t',`a')SWAP_STRUCT($3, $5)popdef(`t') } anext = a.$4a_next; ap = ((Elf$5_$3 *) (uintptr_t) dstaux); *ap = a; } if (anext || cnt) return (0); } if (vnext) return (0); return (1); }') divert(0) /* * C macros to byte swap integral quantities. */ #define SWAP_BYTE(X) do { (void) (X); } while (0) #define SWAP_IDENT(X) do { (void) (X); } while (0) #define SWAP_HALF(X) do { \ uint16_t _x = (uint16_t) (X); \ uint32_t _t = _x & 0xFFU; \ _t <<= 8U; _x >>= 8U; _t |= _x & 0xFFU; \ (X) = (uint16_t) _t; \ } while (0) #define _SWAP_WORD(X, T) do { \ uint32_t _x = (uint32_t) (X); \ uint32_t _t = _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ (X) = (T) _t; \ } while (0) #define SWAP_ADDR32(X) _SWAP_WORD(X, Elf32_Addr) #define SWAP_OFF32(X) _SWAP_WORD(X, Elf32_Off) #define SWAP_SWORD(X) _SWAP_WORD(X, Elf32_Sword) #define SWAP_WORD(X) _SWAP_WORD(X, Elf32_Word) #define _SWAP_WORD64(X, T) do { \ uint64_t _x = (uint64_t) (X); \ uint64_t _t = _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ _t <<= 8; _x >>= 8; _t |= _x & 0xFF; \ (X) = (T) _t; \ } while (0) #define SWAP_ADDR64(X) _SWAP_WORD64(X, Elf64_Addr) #define SWAP_LWORD(X) _SWAP_WORD64(X, Elf64_Lword) #define SWAP_OFF64(X) _SWAP_WORD64(X, Elf64_Off) #define SWAP_SXWORD(X) _SWAP_WORD64(X, Elf64_Sxword) #define SWAP_XWORD(X) _SWAP_WORD64(X, Elf64_Xword) /* * C macros to write out various integral values. * * Note: * - The destination pointer could be unaligned. * - Values are written out in native byte order. * - The destination pointer is incremented after the write. */ #define WRITE_BYTE(P,X) do { \ unsigned char *const _p = (unsigned char *) (P); \ _p[0] = (unsigned char) (X); \ (P) = _p + 1; \ } while (0) #define WRITE_HALF(P,X) do { \ uint16_t _t = (X); \ unsigned char *const _p = (unsigned char *) (P); \ const unsigned char *const _q = (unsigned char *) &_t; \ _p[0] = _q[0]; \ _p[1] = _q[1]; \ (P) = _p + 2; \ } while (0) #define WRITE_WORD(P,X) do { \ uint32_t _t = (uint32_t) (X); \ unsigned char *const _p = (unsigned char *) (P); \ const unsigned char *const _q = (unsigned char *) &_t; \ _p[0] = _q[0]; \ _p[1] = _q[1]; \ _p[2] = _q[2]; \ _p[3] = _q[3]; \ (P) = _p + 4; \ } while (0) #define WRITE_ADDR32(P,X) WRITE_WORD(P,X) #define WRITE_OFF32(P,X) WRITE_WORD(P,X) #define WRITE_SWORD(P,X) WRITE_WORD(P,X) #define WRITE_WORD64(P,X) do { \ uint64_t _t = (uint64_t) (X); \ unsigned char *const _p = (unsigned char *) (P); \ const unsigned char *const _q = (unsigned char *) &_t; \ _p[0] = _q[0]; \ _p[1] = _q[1]; \ _p[2] = _q[2]; \ _p[3] = _q[3]; \ _p[4] = _q[4]; \ _p[5] = _q[5]; \ _p[6] = _q[6]; \ _p[7] = _q[7]; \ (P) = _p + 8; \ } while (0) #define WRITE_ADDR64(P,X) WRITE_WORD64(P,X) #define WRITE_LWORD(P,X) WRITE_WORD64(P,X) #define WRITE_OFF64(P,X) WRITE_WORD64(P,X) #define WRITE_SXWORD(P,X) WRITE_WORD64(P,X) #define WRITE_XWORD(P,X) WRITE_WORD64(P,X) #define WRITE_IDENT(P,X) do { \ (void) memcpy((P), (X), sizeof((X))); \ (P) = (P) + EI_NIDENT; \ } while (0) /* * C macros to read in various integral values. * * Note: * - The source pointer could be unaligned. * - Values are read in native byte order. * - The source pointer is incremented appropriately. */ #define READ_BYTE(P,X) do { \ const unsigned char *const _p = \ (const unsigned char *) (P); \ (X) = _p[0]; \ (P) = (P) + 1; \ } while (0) #define READ_HALF(P,X) do { \ uint16_t _t; \ unsigned char *const _q = (unsigned char *) &_t; \ const unsigned char *const _p = \ (const unsigned char *) (P); \ _q[0] = _p[0]; \ _q[1] = _p[1]; \ (P) = (P) + 2; \ (X) = _t; \ } while (0) #define _READ_WORD(P,X,T) do { \ uint32_t _t; \ unsigned char *const _q = (unsigned char *) &_t; \ const unsigned char *const _p = \ (const unsigned char *) (P); \ _q[0] = _p[0]; \ _q[1] = _p[1]; \ _q[2] = _p[2]; \ _q[3] = _p[3]; \ (P) = (P) + 4; \ (X) = (T) _t; \ } while (0) #define READ_ADDR32(P,X) _READ_WORD(P, X, Elf32_Addr) #define READ_OFF32(P,X) _READ_WORD(P, X, Elf32_Off) #define READ_SWORD(P,X) _READ_WORD(P, X, Elf32_Sword) #define READ_WORD(P,X) _READ_WORD(P, X, Elf32_Word) #define _READ_WORD64(P,X,T) do { \ uint64_t _t; \ unsigned char *const _q = (unsigned char *) &_t; \ const unsigned char *const _p = \ (const unsigned char *) (P); \ _q[0] = _p[0]; \ _q[1] = _p[1]; \ _q[2] = _p[2]; \ _q[3] = _p[3]; \ _q[4] = _p[4]; \ _q[5] = _p[5]; \ _q[6] = _p[6]; \ _q[7] = _p[7]; \ (P) = (P) + 8; \ (X) = (T) _t; \ } while (0) #define READ_ADDR64(P,X) _READ_WORD64(P, X, Elf64_Addr) #define READ_LWORD(P,X) _READ_WORD64(P, X, Elf64_Lword) #define READ_OFF64(P,X) _READ_WORD64(P, X, Elf64_Off) #define READ_SXWORD(P,X) _READ_WORD64(P, X, Elf64_Sxword) #define READ_XWORD(P,X) _READ_WORD64(P, X, Elf64_Xword) #define READ_IDENT(P,X) do { \ (void) memcpy((X), (P), sizeof((X))); \ (P) = (P) + EI_NIDENT; \ } while (0) #define ROUNDUP2(V,N) (V) = ((((V) + (N) - 1)) & ~((N) - 1)) /*[*/ MAKE_TYPE_CONVERTERS(ELF_TYPE_LIST) MAKE_VERSION_CONVERTERS(VDEF,Verdef,Verdaux,vd) MAKE_VERSION_CONVERTERS(VNEED,Verneed,Vernaux,vn) /*]*/ /* * Sections of type ELF_T_BYTE are never byteswapped, consequently a * simple memcpy suffices for both directions of conversion. */ static int _libelf_cvt_BYTE_tox(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { (void) byteswap; if (dsz < count) return (0); if (dst != src) (void) memcpy(dst, src, count); return (1); } /* * Sections of type ELF_T_GNUHASH start with a header containing 4 32-bit * words. Bloom filter data comes next, followed by hash buckets and the * hash chain. * * Bloom filter words are 64 bit wide on ELFCLASS64 objects and are 32 bit * wide on ELFCLASS32 objects. The other objects in this section are 32 * bits wide. * * Argument `srcsz' denotes the number of bytes to be converted. In the * 32-bit case we need to translate `srcsz' to a count of 32-bit words. */ static int _libelf_cvt_GNUHASH32_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t srcsz, int byteswap) { return (_libelf_cvt_WORD_tom(dst, dsz, src, srcsz / sizeof(uint32_t), byteswap)); } static int _libelf_cvt_GNUHASH32_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t srcsz, int byteswap) { return (_libelf_cvt_WORD_tof(dst, dsz, src, srcsz / sizeof(uint32_t), byteswap)); } static int _libelf_cvt_GNUHASH64_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t srcsz, int byteswap) { size_t sz; uint64_t t64, *bloom64; Elf_GNU_Hash_Header *gh; uint32_t n, nbuckets, nchains, maskwords, shift2, symndx, t32; uint32_t *buckets, *chains; sz = 4 * sizeof(uint32_t); /* File header is 4 words long. */ if (dsz < sizeof(Elf_GNU_Hash_Header) || srcsz < sz) return (0); /* Read in the section header and byteswap if needed. */ READ_WORD(src, nbuckets); READ_WORD(src, symndx); READ_WORD(src, maskwords); READ_WORD(src, shift2); srcsz -= sz; if (byteswap) { SWAP_WORD(nbuckets); SWAP_WORD(symndx); SWAP_WORD(maskwords); SWAP_WORD(shift2); } /* Check source buffer and destination buffer sizes. */ sz = nbuckets * sizeof(uint32_t) + maskwords * sizeof(uint64_t); if (srcsz < sz || dsz < sz + sizeof(Elf_GNU_Hash_Header)) return (0); gh = (Elf_GNU_Hash_Header *) (uintptr_t) dst; gh->gh_nbuckets = nbuckets; gh->gh_symndx = symndx; gh->gh_maskwords = maskwords; gh->gh_shift2 = shift2; dsz -= sizeof(Elf_GNU_Hash_Header); dst += sizeof(Elf_GNU_Hash_Header); bloom64 = (uint64_t *) (uintptr_t) dst; /* Copy bloom filter data. */ for (n = 0; n < maskwords; n++) { READ_XWORD(src, t64); if (byteswap) SWAP_XWORD(t64); bloom64[n] = t64; } /* The hash buckets follows the bloom filter. */ dst += maskwords * sizeof(uint64_t); buckets = (uint32_t *) (uintptr_t) dst; for (n = 0; n < nbuckets; n++) { READ_WORD(src, t32); if (byteswap) SWAP_WORD(t32); buckets[n] = t32; } dst += nbuckets * sizeof(uint32_t); /* The hash chain follows the hash buckets. */ dsz -= sz; srcsz -= sz; if (dsz < srcsz) /* Destination lacks space. */ return (0); nchains = srcsz / sizeof(uint32_t); chains = (uint32_t *) (uintptr_t) dst; for (n = 0; n < nchains; n++) { READ_WORD(src, t32); if (byteswap) SWAP_WORD(t32); *chains++ = t32; } return (1); } static int _libelf_cvt_GNUHASH64_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t srcsz, int byteswap) { uint32_t *s32; size_t sz, hdrsz; uint64_t *s64, t64; Elf_GNU_Hash_Header *gh; uint32_t maskwords, n, nbuckets, nchains, t0, t1, t2, t3, t32; hdrsz = 4 * sizeof(uint32_t); /* Header is 4x32 bits. */ if (dsz < hdrsz || srcsz < sizeof(Elf_GNU_Hash_Header)) return (0); gh = (Elf_GNU_Hash_Header *) (uintptr_t) src; t0 = nbuckets = gh->gh_nbuckets; t1 = gh->gh_symndx; t2 = maskwords = gh->gh_maskwords; t3 = gh->gh_shift2; src += sizeof(Elf_GNU_Hash_Header); srcsz -= sizeof(Elf_GNU_Hash_Header); dsz -= hdrsz; sz = gh->gh_nbuckets * sizeof(uint32_t) + gh->gh_maskwords * sizeof(uint64_t); if (srcsz < sz || dsz < sz) return (0); /* Write out the header. */ if (byteswap) { SWAP_WORD(t0); SWAP_WORD(t1); SWAP_WORD(t2); SWAP_WORD(t3); } WRITE_WORD(dst, t0); WRITE_WORD(dst, t1); WRITE_WORD(dst, t2); WRITE_WORD(dst, t3); /* Copy the bloom filter and the hash table. */ s64 = (uint64_t *) (uintptr_t) src; for (n = 0; n < maskwords; n++) { t64 = *s64++; if (byteswap) SWAP_XWORD(t64); WRITE_WORD64(dst, t64); } s32 = (uint32_t *) s64; for (n = 0; n < nbuckets; n++) { t32 = *s32++; if (byteswap) SWAP_WORD(t32); WRITE_WORD(dst, t32); } srcsz -= sz; dsz -= sz; /* Copy out the hash chains. */ if (dsz < srcsz) return (0); nchains = srcsz / sizeof(uint32_t); for (n = 0; n < nchains; n++) { t32 = *s32++; if (byteswap) SWAP_WORD(t32); WRITE_WORD(dst, t32); } return (1); } /* * Elf_Note structures comprise a fixed size header followed by variable * length strings. The fixed size header needs to be byte swapped, but * not the strings. * * Argument `count' denotes the total number of bytes to be converted. * The destination buffer needs to be at least `count' bytes in size. */ static int _libelf_cvt_NOTE_tom(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { uint32_t namesz, descsz, type; Elf_Note *en; size_t sz, hdrsz; if (dsz < count) /* Destination buffer is too small. */ return (0); hdrsz = 3 * sizeof(uint32_t); if (count < hdrsz) /* Source too small. */ return (0); if (!byteswap) { (void) memcpy(dst, src, count); return (1); } /* Process all notes in the section. */ while (count > hdrsz) { /* Read the note header. */ READ_WORD(src, namesz); READ_WORD(src, descsz); READ_WORD(src, type); /* Translate. */ SWAP_WORD(namesz); SWAP_WORD(descsz); SWAP_WORD(type); /* Copy out the translated note header. */ en = (Elf_Note *) (uintptr_t) dst; en->n_namesz = namesz; en->n_descsz = descsz; en->n_type = type; dsz -= sizeof(Elf_Note); dst += sizeof(Elf_Note); count -= hdrsz; ROUNDUP2(namesz, 4U); ROUNDUP2(descsz, 4U); sz = namesz + descsz; if (count < sz || dsz < sz) /* Buffers are too small. */ return (0); (void) memcpy(dst, src, sz); src += sz; dst += sz; count -= sz; dsz -= sz; } return (1); } static int _libelf_cvt_NOTE_tof(unsigned char *dst, size_t dsz, unsigned char *src, size_t count, int byteswap) { uint32_t namesz, descsz, type; Elf_Note *en; size_t sz; if (dsz < count) return (0); if (!byteswap) { (void) memcpy(dst, src, count); return (1); } while (count > sizeof(Elf_Note)) { en = (Elf_Note *) (uintptr_t) src; namesz = en->n_namesz; descsz = en->n_descsz; type = en->n_type; sz = namesz; ROUNDUP2(sz, 4U); sz += descsz; ROUNDUP2(sz, 4U); SWAP_WORD(namesz); SWAP_WORD(descsz); SWAP_WORD(type); WRITE_WORD(dst, namesz); WRITE_WORD(dst, descsz); WRITE_WORD(dst, type); src += sizeof(Elf_Note); if (count < sz) sz = count; (void) memcpy(dst, src, sz); src += sz; dst += sz; count -= sz; } return (1); } struct converters { int (*tof32)(unsigned char *dst, size_t dsz, unsigned char *src, size_t cnt, int byteswap); int (*tom32)(unsigned char *dst, size_t dsz, unsigned char *src, size_t cnt, int byteswap); int (*tof64)(unsigned char *dst, size_t dsz, unsigned char *src, size_t cnt, int byteswap); int (*tom64)(unsigned char *dst, size_t dsz, unsigned char *src, size_t cnt, int byteswap); }; static struct converters cvt[ELF_T_NUM] = { /*[*/ CONVERTER_NAMES(ELF_TYPE_LIST) /*]*/ /* * Types that need hand-coded converters follow. */ [ELF_T_BYTE] = { .tof32 = _libelf_cvt_BYTE_tox, .tom32 = _libelf_cvt_BYTE_tox, .tof64 = _libelf_cvt_BYTE_tox, .tom64 = _libelf_cvt_BYTE_tox }, [ELF_T_NOTE] = { .tof32 = _libelf_cvt_NOTE_tof, .tom32 = _libelf_cvt_NOTE_tom, .tof64 = _libelf_cvt_NOTE_tof, .tom64 = _libelf_cvt_NOTE_tom } }; int (*_libelf_get_translator(Elf_Type t, int direction, int elfclass)) (unsigned char *_dst, size_t dsz, unsigned char *_src, size_t _cnt, int _byteswap) { assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); if (t >= ELF_T_NUM || (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) || (direction != ELF_TOFILE && direction != ELF_TOMEMORY)) return (NULL); return ((elfclass == ELFCLASS32) ? (direction == ELF_TOFILE ? cvt[t].tof32 : cvt[t].tom32) : (direction == ELF_TOFILE ? cvt[t].tof64 : cvt[t].tom64)); } Index: head/contrib/elftoolchain/libelf/libelf_data.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_data.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_data.c (revision 280932) @@ -1,103 +1,101 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_data.c 3080 2014-07-28 08:46:17Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_data.c 3174 2015-03-27 17:13:41Z emaste $"); int _libelf_xlate_shtype(uint32_t sht) { /* * Look for known section types. */ switch (sht) { case SHT_DYNAMIC: return (ELF_T_DYN); case SHT_DYNSYM: return (ELF_T_SYM); case SHT_FINI_ARRAY: return (ELF_T_ADDR); case SHT_GNU_HASH: return (ELF_T_GNUHASH); case SHT_GNU_LIBLIST: return (ELF_T_WORD); case SHT_GROUP: return (ELF_T_WORD); case SHT_HASH: return (ELF_T_WORD); case SHT_INIT_ARRAY: return (ELF_T_ADDR); case SHT_NOBITS: return (ELF_T_BYTE); case SHT_NOTE: return (ELF_T_NOTE); case SHT_PREINIT_ARRAY: return (ELF_T_ADDR); case SHT_PROGBITS: return (ELF_T_BYTE); case SHT_REL: return (ELF_T_REL); case SHT_RELA: return (ELF_T_RELA); case SHT_STRTAB: return (ELF_T_BYTE); case SHT_SYMTAB: return (ELF_T_SYM); case SHT_SYMTAB_SHNDX: return (ELF_T_WORD); case SHT_SUNW_dof: return (ELF_T_BYTE); case SHT_SUNW_move: return (ELF_T_MOVE); case SHT_SUNW_syminfo: return (ELF_T_SYMINFO); case SHT_SUNW_verdef: /* == SHT_GNU_verdef */ return (ELF_T_VDEF); case SHT_SUNW_verneed: /* == SHT_GNU_verneed */ return (ELF_T_VNEED); case SHT_SUNW_versym: /* == SHT_GNU_versym */ return (ELF_T_HALF); default: /* * Values in the range [SHT_LOOS..SHT_HIUSER] (i.e., * OS, processor and user-defined section types) are * legal, but since we do not know anything more about * their semantics, we return a type of ELF_T_BYTE. */ if (sht >= SHT_LOOS && sht <= SHT_HIUSER) return (ELF_T_BYTE); /* * Other values are unsupported. */ return (-1); } } Index: head/contrib/elftoolchain/libelf/libelf_ehdr.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_ehdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_ehdr.c (revision 280932) @@ -1,206 +1,204 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_ehdr.c 3009 2014-03-23 01:49:59Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_ehdr.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Retrieve counts for sections, phdrs and the section string table index * from section header #0 of the ELF object. */ static int _libelf_load_extended(Elf *e, int ec, uint64_t shoff, uint16_t phnum, uint16_t strndx) { Elf_Scn *scn; size_t fsz; int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, size_t _c, int _swap); uint32_t shtype; assert(STAILQ_EMPTY(&e->e_u.e_elf.e_scn)); fsz = _libelf_fsize(ELF_T_SHDR, ec, e->e_version, 1); assert(fsz > 0); if (e->e_rawsize < shoff + fsz) { /* raw file too small */ LIBELF_SET_ERROR(HEADER, 0); return (0); } if ((scn = _libelf_allocate_scn(e, (size_t) 0)) == NULL) return (0); xlator = _libelf_get_translator(ELF_T_SHDR, ELF_TOMEMORY, ec); (*xlator)((unsigned char *) &scn->s_shdr, sizeof(scn->s_shdr), (unsigned char *) e->e_rawfile + shoff, (size_t) 1, e->e_byteorder != LIBELF_PRIVATE(byteorder)); #define GET_SHDR_MEMBER(M) ((ec == ELFCLASS32) ? scn->s_shdr.s_shdr32.M : \ scn->s_shdr.s_shdr64.M) if ((shtype = GET_SHDR_MEMBER(sh_type)) != SHT_NULL) { LIBELF_SET_ERROR(SECTION, 0); return (0); } e->e_u.e_elf.e_nscn = (size_t) GET_SHDR_MEMBER(sh_size); e->e_u.e_elf.e_nphdr = (phnum != PN_XNUM) ? phnum : GET_SHDR_MEMBER(sh_info); e->e_u.e_elf.e_strndx = (strndx != SHN_XINDEX) ? strndx : GET_SHDR_MEMBER(sh_link); #undef GET_SHDR_MEMBER return (1); } #define EHDR_INIT(E,SZ) do { \ Elf##SZ##_Ehdr *eh = (E); \ eh->e_ident[EI_MAG0] = ELFMAG0; \ eh->e_ident[EI_MAG1] = ELFMAG1; \ eh->e_ident[EI_MAG2] = ELFMAG2; \ eh->e_ident[EI_MAG3] = ELFMAG3; \ eh->e_ident[EI_CLASS] = ELFCLASS##SZ; \ eh->e_ident[EI_DATA] = ELFDATANONE; \ eh->e_ident[EI_VERSION] = LIBELF_PRIVATE(version) & 0xFFU; \ eh->e_machine = EM_NONE; \ eh->e_type = ELF_K_NONE; \ eh->e_version = LIBELF_PRIVATE(version); \ } while (0) void * _libelf_ehdr(Elf *e, int ec, int allocate) { void *ehdr; size_t fsz, msz; uint16_t phnum, shnum, strndx; uint64_t shoff; int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (e == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (e->e_class != ELFCLASSNONE && e->e_class != ec) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } if (e->e_version != EV_CURRENT) { LIBELF_SET_ERROR(VERSION, 0); return (NULL); } if (e->e_class == ELFCLASSNONE) e->e_class = ec; if (ec == ELFCLASS32) ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr32; else ehdr = (void *) e->e_u.e_elf.e_ehdr.e_ehdr64; if (ehdr != NULL) /* already have a translated ehdr */ return (ehdr); fsz = _libelf_fsize(ELF_T_EHDR, ec, e->e_version, (size_t) 1); assert(fsz > 0); if (e->e_cmd != ELF_C_WRITE && e->e_rawsize < fsz) { LIBELF_SET_ERROR(HEADER, 0); return (NULL); } msz = _libelf_msize(ELF_T_EHDR, ec, EV_CURRENT); assert(msz > 0); if ((ehdr = calloc((size_t) 1, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) { e->e_u.e_elf.e_ehdr.e_ehdr32 = ehdr; EHDR_INIT(ehdr,32); } else { e->e_u.e_elf.e_ehdr.e_ehdr64 = ehdr; EHDR_INIT(ehdr,64); } if (allocate) e->e_flags |= ELF_F_DIRTY; if (e->e_cmd == ELF_C_WRITE) return (ehdr); xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec); (*xlator)((unsigned char*) ehdr, msz, e->e_rawfile, (size_t) 1, e->e_byteorder != LIBELF_PRIVATE(byteorder)); /* * If extended numbering is being used, read the correct * number of sections and program header entries. */ if (ec == ELFCLASS32) { phnum = ((Elf32_Ehdr *) ehdr)->e_phnum; shnum = ((Elf32_Ehdr *) ehdr)->e_shnum; shoff = ((Elf32_Ehdr *) ehdr)->e_shoff; strndx = ((Elf32_Ehdr *) ehdr)->e_shstrndx; } else { phnum = ((Elf64_Ehdr *) ehdr)->e_phnum; shnum = ((Elf64_Ehdr *) ehdr)->e_shnum; shoff = ((Elf64_Ehdr *) ehdr)->e_shoff; strndx = ((Elf64_Ehdr *) ehdr)->e_shstrndx; } if (shnum >= SHN_LORESERVE || (shoff == 0LL && (shnum != 0 || phnum == PN_XNUM || strndx == SHN_XINDEX))) { LIBELF_SET_ERROR(HEADER, 0); return (NULL); } if (shnum != 0 || shoff == 0LL) { /* not using extended numbering */ e->e_u.e_elf.e_nphdr = phnum; e->e_u.e_elf.e_nscn = shnum; e->e_u.e_elf.e_strndx = strndx; } else if (_libelf_load_extended(e, ec, shoff, phnum, strndx) == 0) return (NULL); return (ehdr); } Index: head/contrib/elftoolchain/libelf/libelf_extended.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_extended.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_extended.c (revision 280932) @@ -1,136 +1,134 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_extended.c 3005 2014-03-22 07:43:25Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_extended.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Retrieve section #0, allocating a new section if needed. */ static Elf_Scn * _libelf_getscn0(Elf *e) { Elf_Scn *s; if ((s = STAILQ_FIRST(&e->e_u.e_elf.e_scn)) != NULL) return (s); return (_libelf_allocate_scn(e, (size_t) SHN_UNDEF)); } int _libelf_setshnum(Elf *e, void *eh, int ec, size_t shnum) { Elf_Scn *scn; if (shnum >= SHN_LORESERVE) { if ((scn = _libelf_getscn0(e)) == NULL) return (0); assert(scn->s_ndx == SHN_UNDEF); if (ec == ELFCLASS32) scn->s_shdr.s_shdr32.sh_size = shnum; else scn->s_shdr.s_shdr64.sh_size = shnum; (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); shnum = 0; } if (ec == ELFCLASS32) ((Elf32_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU; else ((Elf64_Ehdr *) eh)->e_shnum = shnum & 0xFFFFU; return (1); } int _libelf_setshstrndx(Elf *e, void *eh, int ec, size_t shstrndx) { Elf_Scn *scn; if (shstrndx >= SHN_LORESERVE) { if ((scn = _libelf_getscn0(e)) == NULL) return (0); assert(scn->s_ndx == SHN_UNDEF); if (ec == ELFCLASS32) scn->s_shdr.s_shdr32.sh_link = shstrndx; else scn->s_shdr.s_shdr64.sh_link = shstrndx; (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); shstrndx = SHN_XINDEX; } if (ec == ELFCLASS32) ((Elf32_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU; else ((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx & 0xFFFFU; return (1); } int _libelf_setphnum(Elf *e, void *eh, int ec, size_t phnum) { Elf_Scn *scn; if (phnum >= PN_XNUM) { if ((scn = _libelf_getscn0(e)) == NULL) return (0); assert(scn->s_ndx == SHN_UNDEF); if (ec == ELFCLASS32) scn->s_shdr.s_shdr32.sh_info = phnum; else scn->s_shdr.s_shdr64.sh_info = phnum; (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); phnum = PN_XNUM; } if (ec == ELFCLASS32) ((Elf32_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU; else ((Elf64_Ehdr *) eh)->e_phnum = phnum & 0xFFFFU; return (1); } Index: head/contrib/elftoolchain/libelf/libelf_msize.m4 =================================================================== --- head/contrib/elftoolchain/libelf/libelf_msize.m4 (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_msize.m4 (revision 280932) @@ -1,108 +1,106 @@ /*- * Copyright (c) 2006,2008-2011 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_msize.m4 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_msize.m4 3174 2015-03-27 17:13:41Z emaste $"); /* WARNING: GENERATED FROM __file__. */ struct msize { size_t msz32; size_t msz64; }; divert(-1) include(SRCDIR`/elf_types.m4') /* * ELF types whose memory representations have a variable size. */ define(BYTE_SIZE, 1) define(GNUHASH_SIZE, 1) define(NOTE_SIZE, 1) define(VDEF_SIZE, 1) define(VNEED_SIZE, 1) /* * Unimplemented types. */ define(MOVEP_SIZE, 0) define(SXWORD_SIZE32, 0) define(XWORD_SIZE32, 0) define(`DEFINE_ELF_MSIZE', `ifdef($1`_SIZE', `define($1_SIZE32,$1_SIZE) define($1_SIZE64,$1_SIZE)', `ifdef($1`_SIZE32',`', `define($1_SIZE32,sizeof(Elf32_$2))') ifdef($1`_SIZE64',`', `define($1_SIZE64,sizeof(Elf64_$2))')')') define(`DEFINE_ELF_MSIZES', `ifelse($#,1,`', `DEFINE_ELF_MSIZE($1) DEFINE_ELF_MSIZES(shift($@))')') DEFINE_ELF_MSIZES(ELF_TYPE_LIST) define(`MSIZE', `[ELF_T_$1] = { .msz32 = $1_SIZE32, .msz64 = $1_SIZE64 }, ') define(`MSIZES', `ifelse($#,1,`', `MSIZE($1) MSIZES(shift($@))')') divert(0) static struct msize msize[ELF_T_NUM] = { MSIZES(ELF_TYPE_LIST) }; size_t _libelf_msize(Elf_Type t, int elfclass, unsigned int version) { size_t sz; assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); assert((signed) t >= ELF_T_FIRST && t <= ELF_T_LAST); if (version != EV_CURRENT) { LIBELF_SET_ERROR(VERSION, 0); return (0); } sz = (elfclass == ELFCLASS32) ? msize[t].msz32 : msize[t].msz64; return (sz); } Index: head/contrib/elftoolchain/libelf/libelf_phdr.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_phdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_phdr.c (revision 280932) @@ -1,155 +1,153 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_phdr.c 3009 2014-03-23 01:49:59Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_phdr.c 3174 2015-03-27 17:13:41Z emaste $"); void * _libelf_getphdr(Elf *e, int ec) { size_t phnum; size_t fsz, msz; uint64_t phoff; Elf32_Ehdr *eh32; Elf64_Ehdr *eh64; void *ehdr, *phdr; int (*xlator)(unsigned char *_d, size_t _dsz, unsigned char *_s, size_t _c, int _swap); assert(ec == ELFCLASS32 || ec == ELFCLASS64); if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((phdr = (ec == ELFCLASS32 ? (void *) e->e_u.e_elf.e_phdr.e_phdr32 : (void *) e->e_u.e_elf.e_phdr.e_phdr64)) != NULL) return (phdr); /* * Check the PHDR related fields in the EHDR for sanity. */ if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) return (NULL); phnum = e->e_u.e_elf.e_nphdr; if (ec == ELFCLASS32) { eh32 = (Elf32_Ehdr *) ehdr; phoff = (uint64_t) eh32->e_phoff; } else { eh64 = (Elf64_Ehdr *) ehdr; phoff = (uint64_t) eh64->e_phoff; } fsz = gelf_fsize(e, ELF_T_PHDR, phnum, e->e_version); assert(fsz > 0); if ((uint64_t) e->e_rawsize < (phoff + fsz)) { LIBELF_SET_ERROR(HEADER, 0); return (NULL); } msz = _libelf_msize(ELF_T_PHDR, ec, EV_CURRENT); assert(msz > 0); if ((phdr = calloc(phnum, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) e->e_u.e_elf.e_phdr.e_phdr32 = phdr; else e->e_u.e_elf.e_phdr.e_phdr64 = phdr; xlator = _libelf_get_translator(ELF_T_PHDR, ELF_TOMEMORY, ec); (*xlator)(phdr, phnum * msz, e->e_rawfile + phoff, phnum, e->e_byteorder != LIBELF_PRIVATE(byteorder)); return (phdr); } void * _libelf_newphdr(Elf *e, int ec, size_t count) { void *ehdr, *newphdr, *oldphdr; size_t msz; if (e == NULL) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if ((ehdr = _libelf_ehdr(e, ec, 0)) == NULL) { LIBELF_SET_ERROR(SEQUENCE, 0); return (NULL); } assert(e->e_class == ec); assert(ec == ELFCLASS32 || ec == ELFCLASS64); assert(e->e_version == EV_CURRENT); msz = _libelf_msize(ELF_T_PHDR, ec, e->e_version); assert(msz > 0); newphdr = NULL; if (count > 0 && (newphdr = calloc(count, msz)) == NULL) { LIBELF_SET_ERROR(RESOURCE, 0); return (NULL); } if (ec == ELFCLASS32) { if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL) free(oldphdr); e->e_u.e_elf.e_phdr.e_phdr32 = (Elf32_Phdr *) newphdr; } else { if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr64) != NULL) free(oldphdr); e->e_u.e_elf.e_phdr.e_phdr64 = (Elf64_Phdr *) newphdr; } e->e_u.e_elf.e_nphdr = count; elf_flagphdr(e, ELF_C_SET, ELF_F_DIRTY); return (newphdr); } Index: head/contrib/elftoolchain/libelf/libelf_shdr.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_shdr.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_shdr.c (revision 280932) @@ -1,56 +1,54 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_shdr.c 2225 2011-11-26 18:55:54Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_shdr.c 3174 2015-03-27 17:13:41Z emaste $"); void * _libelf_getshdr(Elf_Scn *s, int ec) { Elf *e; if (s == NULL || (e = s->s_elf) == NULL || e->e_kind != ELF_K_ELF) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } if (ec == ELFCLASSNONE) ec = e->e_class; if (ec != e->e_class) { LIBELF_SET_ERROR(CLASS, 0); return (NULL); } return ((void *) &s->s_shdr); } Index: head/contrib/elftoolchain/libelf/libelf_xlate.c =================================================================== --- head/contrib/elftoolchain/libelf/libelf_xlate.c (revision 280931) +++ head/contrib/elftoolchain/libelf/libelf_xlate.c (revision 280932) @@ -1,150 +1,148 @@ /*- * Copyright (c) 2006,2008 Joseph Koshy * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include - #include #include #include "_libelf.h" -ELFTC_VCSID("$Id: libelf_xlate.c 3007 2014-03-22 08:10:14Z jkoshy $"); +ELFTC_VCSID("$Id: libelf_xlate.c 3174 2015-03-27 17:13:41Z emaste $"); /* * Translate to/from the file representation of ELF objects. * * Translation could potentially involve the following * transformations: * * - an endianness conversion, * - a change of layout, as the file representation of ELF objects * can differ from their in-memory representation. * - a change in representation due to a layout version change. */ Elf_Data * _libelf_xlate(Elf_Data *dst, const Elf_Data *src, unsigned int encoding, int elfclass, int direction) { int byteswap; size_t cnt, dsz, fsz, msz; uintptr_t sb, se, db, de; if (encoding == ELFDATANONE) encoding = LIBELF_PRIVATE(byteorder); if ((encoding != ELFDATA2LSB && encoding != ELFDATA2MSB) || dst == NULL || src == NULL || dst == src) { LIBELF_SET_ERROR(ARGUMENT, 0); return (NULL); } assert(elfclass == ELFCLASS32 || elfclass == ELFCLASS64); assert(direction == ELF_TOFILE || direction == ELF_TOMEMORY); if (dst->d_version != src->d_version) { LIBELF_SET_ERROR(UNIMPL, 0); return (NULL); } if (src->d_buf == NULL || dst->d_buf == NULL) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } if ((int) src->d_type < 0 || src->d_type >= ELF_T_NUM) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } if ((fsz = (elfclass == ELFCLASS32 ? elf32_fsize : elf64_fsize) (src->d_type, (size_t) 1, src->d_version)) == 0) return (NULL); msz = _libelf_msize(src->d_type, elfclass, src->d_version); assert(msz > 0); if (src->d_size % (direction == ELF_TOMEMORY ? fsz : msz)) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } /* * Determine the number of objects that need to be converted, and * the space required for the converted objects in the destination * buffer. */ if (direction == ELF_TOMEMORY) { cnt = (size_t) src->d_size / fsz; dsz = cnt * msz; } else { cnt = (size_t) src->d_size / msz; dsz = cnt * fsz; } if (dst->d_size < dsz) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } sb = (uintptr_t) src->d_buf; se = sb + (size_t) src->d_size; db = (uintptr_t) dst->d_buf; de = db + (size_t) dst->d_size; /* * Check for overlapping buffers. Note that db == sb is * allowed. */ if (db != sb && de > sb && se > db) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } if ((direction == ELF_TOMEMORY ? db : sb) % _libelf_malign(src->d_type, elfclass)) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } dst->d_type = src->d_type; dst->d_size = dsz; byteswap = encoding != LIBELF_PRIVATE(byteorder); if (src->d_size == 0 || (db == sb && !byteswap && fsz == msz)) return (dst); /* nothing more to do */ if (!(_libelf_get_translator(src->d_type, direction, elfclass)) (dst->d_buf, dsz, src->d_buf, cnt, byteswap)) { LIBELF_SET_ERROR(DATA, 0); return (NULL); } return (dst); } Index: head/contrib/elftoolchain/libelftc/_libelftc.h =================================================================== --- head/contrib/elftoolchain/libelftc/_libelftc.h (revision 280931) +++ head/contrib/elftoolchain/libelftc/_libelftc.h (revision 280932) @@ -1,89 +1,93 @@ /*- * Copyright (c) 2009 Kai Wang * Copyright (c) 2007,2008 Hyogeol Lee * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: _libelftc.h 2856 2013-01-04 16:00:26Z jkoshy $ + * $Id: _libelftc.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef __LIBELFTC_H_ #define __LIBELFTC_H_ #include #include "_elftc.h" struct _Elftc_Bfd_Target { const char *bt_name; /* target name. */ unsigned int bt_type; /* target type. */ unsigned int bt_byteorder; /* elf target byteorder. */ unsigned int bt_elfclass; /* elf target class (32/64bit). */ unsigned int bt_machine; /* elf target arch. */ unsigned int bt_osabi; /* elf target abi. */ }; extern struct _Elftc_Bfd_Target _libelftc_targets[]; /** @brief Dynamic vector data for string. */ struct vector_str { /** Current size */ size_t size; /** Total capacity */ size_t capacity; /** String array */ char **container; }; #define BUFFER_GROWFACTOR 1.618 #define ELFTC_FAILURE 0 #define ELFTC_ISDIGIT(C) (isdigit((C) & 0xFF)) #define ELFTC_SUCCESS 1 #define VECTOR_DEF_CAPACITY 8 -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif char *cpp_demangle_ARM(const char *_org); char *cpp_demangle_gnu2(const char *_org); char *cpp_demangle_gnu3(const char *_org); bool is_cpp_mangled_ARM(const char *_org); bool is_cpp_mangled_gnu2(const char *_org); bool is_cpp_mangled_gnu3(const char *_org); unsigned int libelftc_hash_string(const char *); void vector_str_dest(struct vector_str *_vec); int vector_str_find(const struct vector_str *_vs, const char *_str, size_t _len); char *vector_str_get_flat(const struct vector_str *_vs, size_t *_len); bool vector_str_init(struct vector_str *_vs); bool vector_str_pop(struct vector_str *_vs); bool vector_str_push(struct vector_str *_vs, const char *_str, size_t _len); bool vector_str_push_vector_head(struct vector_str *_dst, struct vector_str *_org); char *vector_str_substr(const struct vector_str *_vs, size_t _begin, size_t _end, size_t *_rlen); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* __LIBELFTC_H */ Index: head/contrib/elftoolchain/libelftc/elftc_bfdtarget.c =================================================================== --- head/contrib/elftoolchain/libelftc/elftc_bfdtarget.c (revision 280931) +++ head/contrib/elftoolchain/libelftc/elftc_bfdtarget.c (revision 280932) @@ -1,75 +1,73 @@ /*- * Copyright (c) 2008,2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include #include #include "_libelftc.h" -ELFTC_VCSID("$Id: elftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $"); +ELFTC_VCSID("$Id: elftc_bfdtarget.c 3174 2015-03-27 17:13:41Z emaste $"); Elftc_Bfd_Target * elftc_bfd_find_target(const char *tgt_name) { Elftc_Bfd_Target *tgt; for (tgt = _libelftc_targets; tgt->bt_name; tgt++) if (!strcmp(tgt_name, tgt->bt_name)) return (tgt); return (NULL); /* not found */ } Elftc_Bfd_Target_Flavor elftc_bfd_target_flavor(Elftc_Bfd_Target *tgt) { return (tgt->bt_type); } unsigned int elftc_bfd_target_byteorder(Elftc_Bfd_Target *tgt) { return (tgt->bt_byteorder); } unsigned int elftc_bfd_target_class(Elftc_Bfd_Target *tgt) { return (tgt->bt_elfclass); } unsigned int elftc_bfd_target_machine(Elftc_Bfd_Target *tgt) { return (tgt->bt_machine); } Index: head/contrib/elftoolchain/libelftc/elftc_demangle.c =================================================================== --- head/contrib/elftoolchain/libelftc/elftc_demangle.c (revision 280931) +++ head/contrib/elftoolchain/libelftc/elftc_demangle.c (revision 280932) @@ -1,109 +1,107 @@ /*- * Copyright (c) 2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include #include #include #include #include #include "_libelftc.h" -ELFTC_VCSID("$Id: elftc_demangle.c 3030 2014-05-01 06:30:48Z kaiwang27 $"); +ELFTC_VCSID("$Id: elftc_demangle.c 3174 2015-03-27 17:13:41Z emaste $"); static int is_mangled(const char *s, int style) { switch (style) { case ELFTC_DEM_ARM: return (is_cpp_mangled_ARM(s) ? style : 0); case ELFTC_DEM_GNU2: return (is_cpp_mangled_gnu2(s) ? style : 0); case ELFTC_DEM_GNU3: return (is_cpp_mangled_gnu3(s) ? style : 0); } /* No style or invalid style spcified, try to guess. */ if (is_cpp_mangled_gnu3(s)) return (ELFTC_DEM_GNU3); if (is_cpp_mangled_gnu2(s)) return (ELFTC_DEM_GNU2); if (is_cpp_mangled_ARM(s)) return (ELFTC_DEM_ARM); /* Cannot be demangled. */ return (0); } static char * demangle(const char *s, int style, int rc) { (void) rc; /* XXX */ switch (style) { case ELFTC_DEM_ARM: return (cpp_demangle_ARM(s)); case ELFTC_DEM_GNU2: return (cpp_demangle_gnu2(s)); case ELFTC_DEM_GNU3: return (cpp_demangle_gnu3(s)); default: assert(0); return (NULL); } } int elftc_demangle(const char *mangledname, char *buffer, size_t bufsize, unsigned int flags) { int style, rc; char *rlt; style = flags & 0xFFFF; rc = flags >> 16; if (mangledname == NULL || ((style = is_mangled(mangledname, style)) == 0)) { errno = EINVAL; return (-1); } if ((rlt = demangle(mangledname, style, rc)) == NULL) { errno = EINVAL; return (-1); } if (buffer == NULL || bufsize < strlen(rlt) + 1) { free(rlt); errno = ENAMETOOLONG; return (-1); } strncpy(buffer, rlt, bufsize); buffer[bufsize - 1] = '\0'; free(rlt); return (0); } Index: head/contrib/elftoolchain/libelftc/libelftc.h =================================================================== --- head/contrib/elftoolchain/libelftc/libelftc.h (revision 280931) +++ head/contrib/elftoolchain/libelftc/libelftc.h (revision 280932) @@ -1,92 +1,96 @@ /*- * Copyright (c) 2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: users/kaiwang27/elftc/libelftc.h 392 2009-05-31 19:17:46Z kaiwang27 $ - * $Id: libelftc.h 3031 2014-05-01 17:45:41Z jkoshy $ + * $Id: libelftc.h 3174 2015-03-27 17:13:41Z emaste $ */ #ifndef _LIBELFTC_H_ #define _LIBELFTC_H_ #include #include /* * Types meant to be opaque to the consumers of these APIs. */ typedef struct _Elftc_Bfd_Target Elftc_Bfd_Target; typedef struct _Elftc_String_Table Elftc_String_Table; /* Target types. */ typedef enum { ETF_NONE, ETF_ELF, ETF_BINARY, ETF_SREC, ETF_IHEX } Elftc_Bfd_Target_Flavor; /* * Demangler flags. */ /* Name mangling style. */ #define ELFTC_DEM_UNKNOWN 0x00000000U /* Not specified. */ #define ELFTC_DEM_ARM 0x00000001U /* C++ Ann. Ref. Manual. */ #define ELFTC_DEM_GNU2 0x00000002U /* GNU version 2. */ #define ELFTC_DEM_GNU3 0x00000004U /* GNU version 3. */ /* Demangling behaviour control. */ #define ELFTC_DEM_NOPARAM 0x00010000U -__BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif Elftc_Bfd_Target *elftc_bfd_find_target(const char *_tgt_name); Elftc_Bfd_Target_Flavor elftc_bfd_target_flavor(Elftc_Bfd_Target *_tgt); unsigned int elftc_bfd_target_byteorder(Elftc_Bfd_Target *_tgt); unsigned int elftc_bfd_target_class(Elftc_Bfd_Target *_tgt); unsigned int elftc_bfd_target_machine(Elftc_Bfd_Target *_tgt); int elftc_copyfile(int _srcfd, int _dstfd); int elftc_demangle(const char *_mangledname, char *_buffer, size_t _bufsize, unsigned int _flags); int elftc_set_timestamps(const char *_filename, struct stat *_sb); Elftc_String_Table *elftc_string_table_create(int _hint); void elftc_string_table_destroy(Elftc_String_Table *_table); Elftc_String_Table *elftc_string_table_from_section(Elf_Scn *_scn, int _hint); const char *elftc_string_table_image(Elftc_String_Table *_table, size_t *_sz); size_t elftc_string_table_insert(Elftc_String_Table *_table, const char *_string); size_t elftc_string_table_lookup(Elftc_String_Table *_table, const char *_string); int elftc_string_table_remove(Elftc_String_Table *_table, const char *_string); const char *elftc_string_table_to_string(Elftc_String_Table *_table, size_t offset); const char *elftc_version(void); -__END_DECLS +#ifdef __cplusplus +} +#endif #endif /* _LIBELFTC_H_ */ Index: head/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c =================================================================== --- head/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c (revision 280931) +++ head/contrib/elftoolchain/libelftc/libelftc_bfdtarget.c (revision 280932) @@ -1,383 +1,381 @@ /*- * Copyright (c) 2008,2009 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include - #include #include #include #include "_libelftc.h" -ELFTC_VCSID("$Id: libelftc_bfdtarget.c 2251 2011-11-30 16:50:06Z jkoshy $"); +ELFTC_VCSID("$Id: libelftc_bfdtarget.c 3174 2015-03-27 17:13:41Z emaste $"); struct _Elftc_Bfd_Target _libelftc_targets[] = { { .bt_name = "binary", .bt_type = ETF_BINARY, }, { .bt_name = "elf32-avr", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_AVR, }, { .bt_name = "elf32-big", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, }, { .bt_name = "elf32-bigarm", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_ARM, }, { .bt_name = "elf32-bigmips", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_MIPS, }, { .bt_name = "elf32-i386", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_386, }, { .bt_name = "elf32-i386-freebsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_386, .bt_osabi = ELFOSABI_FREEBSD, }, { .bt_name = "elf32-ia64-big", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_IA_64, }, { .bt_name = "elf32-little", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, }, { .bt_name = "elf32-littlearm", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_ARM, }, { .bt_name = "elf32-littlemips", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_MIPS, }, { .bt_name = "elf32-powerpc", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_PPC, }, { .bt_name = "elf32-powerpcle", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_PPC, }, { .bt_name = "elf32-sh", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, }, { .bt_name = "elf32-shl", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, }, { .bt_name = "elf32-sh-nbsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_NETBSD, }, { .bt_name = "elf32-shl-nbsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_NETBSD, }, { .bt_name = "elf32-shbig-linux", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_LINUX, }, { .bt_name = "elf32-sh-linux", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_LINUX, }, { .bt_name = "elf32-sparc", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS32, .bt_machine = EM_SPARC, }, { .bt_name = "elf64-alpha", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_ALPHA, }, { .bt_name = "elf64-alpha-freebsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_ALPHA, .bt_osabi = ELFOSABI_FREEBSD }, { .bt_name = "elf64-big", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, }, { .bt_name = "elf64-bigmips", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_MIPS, }, { .bt_name = "elf64-ia64-big", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_IA_64, }, { .bt_name = "elf64-ia64-little", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_IA_64, }, { .bt_name = "elf64-little", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, }, { .bt_name = "elf64-littlemips", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_MIPS, }, { .bt_name = "elf64-powerpc", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_PPC64, }, { .bt_name = "elf64-powerpcle", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_PPC64, }, { .bt_name = "elf64-sh64", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, }, { .bt_name = "elf64-sh64l", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, }, { .bt_name = "elf64-sh64-nbsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_NETBSD, }, { .bt_name = "elf64-sh64l-nbsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_NETBSD, }, { .bt_name = "elf64-sh64big-linux", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_LINUX, }, { .bt_name = "elf64-sh64-linux", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SH, .bt_osabi = ELFOSABI_LINUX, }, { .bt_name = "elf64-sparc", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SPARCV9, }, { .bt_name = "elf64-sparc-freebsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2MSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_SPARCV9, .bt_osabi = ELFOSABI_FREEBSD }, { .bt_name = "elf64-x86-64", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_X86_64, }, { .bt_name = "elf64-x86-64-freebsd", .bt_type = ETF_ELF, .bt_byteorder = ELFDATA2LSB, .bt_elfclass = ELFCLASS64, .bt_machine = EM_X86_64, .bt_osabi = ELFOSABI_FREEBSD }, { .bt_name = "ihex", .bt_type = ETF_IHEX, }, { .bt_name = "srec", .bt_type = ETF_SREC, }, { .bt_name = "symbolsrec", .bt_type = ETF_SREC, }, { .bt_name = NULL, .bt_type = ETF_NONE, }, }; Index: head/contrib/elftoolchain/nm/nm.c =================================================================== --- head/contrib/elftoolchain/nm/nm.c (revision 280931) +++ head/contrib/elftoolchain/nm/nm.c (revision 280932) @@ -1,2098 +1,2119 @@ /*- * Copyright (c) 2007 Hyogeol Lee * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer * in this position and unchanged. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: nm.c 3145 2015-02-15 18:04:37Z emaste $"); +ELFTC_VCSID("$Id: nm.c 3179 2015-03-31 19:38:56Z emaste $"); /* symbol information list */ STAILQ_HEAD(sym_head, sym_entry); struct sym_entry { char *name; GElf_Sym *sym; STAILQ_ENTRY(sym_entry) sym_entries; }; typedef int (*fn_sort)(const void *, const void *); typedef void (*fn_elem_print)(char, const char *, const GElf_Sym *, const char *); typedef void (*fn_sym_print)(const GElf_Sym *); typedef int (*fn_filter)(char, const GElf_Sym *, const char *); /* output filter list */ static SLIST_HEAD(filter_head, filter_entry) nm_out_filter = SLIST_HEAD_INITIALIZER(nm_out_filter); struct filter_entry { fn_filter fn; SLIST_ENTRY(filter_entry) filter_entries; }; struct sym_print_data { struct sym_head *headp; size_t sh_num, list_num; const char *t_table, **s_table, *filename, *objname; }; struct nm_prog_info { const char *name; const char *def_filename; }; /* List for line number information. */ struct line_info_entry { uint64_t addr; /* address */ uint64_t line; /* line number */ char *file; /* file name with path */ SLIST_ENTRY(line_info_entry) entries; }; SLIST_HEAD(line_info_head, line_info_entry); /* List for function line number information. */ struct func_info_entry { char *name; /* function name */ char *file; /* file name with path */ uint64_t lowpc; /* low address */ uint64_t highpc; /* high address */ uint64_t line; /* line number */ SLIST_ENTRY(func_info_entry) entries; }; SLIST_HEAD(func_info_head, func_info_entry); /* List for variable line number information. */ struct var_info_entry { char *name; /* variable name */ char *file; /* file name with path */ uint64_t addr; /* address */ uint64_t line; /* line number */ SLIST_ENTRY(var_info_entry) entries; }; SLIST_HEAD(var_info_head, var_info_entry); /* output numric type */ enum radix { RADIX_OCT, RADIX_HEX, RADIX_DEC }; /* output symbol type, PRINT_SYM_DYN for dynamic symbol only */ enum print_symbol { PRINT_SYM_SYM, PRINT_SYM_DYN }; /* output name type */ enum print_name { PRINT_NAME_NONE, PRINT_NAME_FULL, PRINT_NAME_MULTI }; struct nm_prog_options { enum print_symbol print_symbol; enum print_name print_name; enum radix t; int demangle_type; bool print_debug; bool print_armap; int print_size; bool debug_line; int def_only; bool undef_only; int sort_size; bool sort_reverse; int no_demangle; /* * function pointer to sort symbol list. * possible function - cmp_name, cmp_none, cmp_size, cmp_value */ fn_sort sort_fn; /* * function pointer to print symbol elem. * possible function - sym_elem_print_all * sym_elem_print_all_portable * sym_elem_print_all_sysv */ fn_elem_print elem_print_fn; fn_sym_print value_print_fn; fn_sym_print size_print_fn; }; #define CHECK_SYM_PRINT_DATA(p) (p->headp == NULL || p->sh_num == 0 || \ p->t_table == NULL || p->s_table == NULL || p->filename == NULL) #define IS_SYM_TYPE(t) ((t) == '?' || isalpha((t)) != 0) #define IS_UNDEF_SYM_TYPE(t) ((t) == 'U' || (t) == 'v' || (t) == 'w') #define UNUSED(p) ((void)p) static int cmp_name(const void *, const void *); static int cmp_none(const void *, const void *); static int cmp_size(const void *, const void *); static int cmp_value(const void *, const void *); static void filter_dest(void); static int filter_insert(fn_filter); static void get_opt(int, char **); static int get_sym(Elf *, struct sym_head *, int, size_t, size_t, const char *, const char **, int); static const char * get_sym_name(Elf *, const GElf_Sym *, size_t, const char **, int); static char get_sym_type(const GElf_Sym *, const char *); static void global_dest(void); static void global_init(void); static bool is_sec_data(GElf_Shdr *); static bool is_sec_debug(const char *); static bool is_sec_nobits(GElf_Shdr *); static bool is_sec_readonly(GElf_Shdr *); static bool is_sec_text(GElf_Shdr *); static void print_ar_index(int, Elf *); static void print_header(const char *, const char *); static void print_version(void); static int read_elf(Elf *, const char *, Elf_Kind); static int read_object(const char *); static int read_files(int, char **); static void set_opt_value_print_fn(enum radix); static int sym_elem_def(char, const GElf_Sym *, const char *); static int sym_elem_global(char, const GElf_Sym *, const char *); static int sym_elem_global_static(char, const GElf_Sym *, const char *); static int sym_elem_nondebug(char, const GElf_Sym *, const char *); static int sym_elem_nonzero_size(char, const GElf_Sym *, const char *); static void sym_elem_print_all(char, const char *, const GElf_Sym *, const char *); static void sym_elem_print_all_portable(char, const char *, const GElf_Sym *, const char *); static void sym_elem_print_all_sysv(char, const char *, const GElf_Sym *, const char *); static int sym_elem_undef(char, const GElf_Sym *, const char *); static void sym_list_dest(struct sym_head *); static int sym_list_insert(struct sym_head *, const char *, const GElf_Sym *); static void sym_list_print(struct sym_print_data *, struct func_info_head *, struct var_info_head *, struct line_info_head *); static void sym_list_print_each(struct sym_entry *, struct sym_print_data *, struct func_info_head *, struct var_info_head *, struct line_info_head *); static struct sym_entry *sym_list_sort(struct sym_print_data *); static void sym_size_oct_print(const GElf_Sym *); static void sym_size_hex_print(const GElf_Sym *); static void sym_size_dec_print(const GElf_Sym *); static void sym_value_oct_print(const GElf_Sym *); static void sym_value_hex_print(const GElf_Sym *); static void sym_value_dec_print(const GElf_Sym *); static void usage(int); static struct nm_prog_info nm_info; static struct nm_prog_options nm_opts; static int nm_elfclass; /* * Point to current sym_print_data to use portable qsort function. * (e.g. There is no qsort_r function in NetBSD.) * * Using in sym_list_sort. */ static struct sym_print_data *nm_print_data; static const struct option nm_longopts[] = { { "debug-syms", no_argument, NULL, 'a' }, { "defined-only", no_argument, &nm_opts.def_only, 1}, { "demangle", optional_argument, NULL, 'C' }, { "dynamic", no_argument, NULL, 'D' }, { "extern-only", no_argument, NULL, 'g' }, { "format", required_argument, NULL, 'F' }, { "help", no_argument, NULL, 'h' }, { "line-numbers", no_argument, NULL, 'l' }, { "no-demangle", no_argument, &nm_opts.no_demangle, 1}, { "no-sort", no_argument, NULL, 'p' }, { "numeric-sort", no_argument, NULL, 'v' }, { "print-armap", no_argument, NULL, 's' }, { "print-file-name", no_argument, NULL, 'A' }, { "print-size", no_argument, NULL, 'S' }, { "radix", required_argument, NULL, 't' }, { "reverse-sort", no_argument, NULL, 'r' }, { "size-sort", no_argument, &nm_opts.sort_size, 1}, { "undefined-only", no_argument, NULL, 'u' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; #if defined(ELFTC_NEED_BYTEORDER_EXTENSIONS) static __inline uint32_t be32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); } static __inline uint32_t le32dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); } static __inline uint64_t be64dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); } static __inline uint64_t le64dec(const void *pp) { unsigned char const *p = (unsigned char const *)pp; return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); } #endif static int cmp_name(const void *l, const void *r) { assert(l != NULL); assert(r != NULL); assert(((const struct sym_entry *)l)->name != NULL); assert(((const struct sym_entry *)r)->name != NULL); return (strcmp(((const struct sym_entry *)l)->name, ((const struct sym_entry *)r)->name)); } static int cmp_none(const void *l, const void *r) { UNUSED(l); UNUSED(r); return (0); } /* Size comparison. If l and r have same size, compare their name. */ static int cmp_size(const void *lp, const void *rp) { const struct sym_entry *l, *r; l = lp; r = rp; assert(l != NULL); assert(l->name != NULL); assert(l->sym != NULL); assert(r != NULL); assert(r->name != NULL); assert(r->sym != NULL); if (l->sym->st_size == r->sym->st_size) return (strcmp(l->name, r->name)); return (l->sym->st_size - r->sym->st_size); } /* Value comparison. Undefined symbols come first. */ static int cmp_value(const void *lp, const void *rp) { const struct sym_entry *l, *r; const char *ttable; int l_is_undef, r_is_undef; l = lp; r = rp; assert(nm_print_data != NULL); ttable = nm_print_data->t_table; assert(l != NULL); assert(l->name != NULL); assert(l->sym != NULL); assert(r != NULL); assert(r->name != NULL); assert(r->sym != NULL); assert(ttable != NULL); l_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(l->sym, ttable)) ? 1 : 0; r_is_undef = IS_UNDEF_SYM_TYPE(get_sym_type(r->sym, ttable)) ? 1 : 0; assert(l_is_undef + r_is_undef >= 0); assert(l_is_undef + r_is_undef <= 2); switch (l_is_undef + r_is_undef) { case 0: /* Both defined */ if (l->sym->st_value == r->sym->st_value) return (strcmp(l->name, r->name)); - return (l->sym->st_value - r->sym->st_value); + return (l->sym->st_value > r->sym->st_value ? 1 : -1); case 1: /* One undefined */ return (l_is_undef == 0 ? 1 : -1); case 2: /* Both undefined */ return (strcmp(l->name, r->name)); } /* NOTREACHED */ return (l->sym->st_value - r->sym->st_value); } static void filter_dest(void) { struct filter_entry *e; while (!SLIST_EMPTY(&nm_out_filter)) { e = SLIST_FIRST(&nm_out_filter); SLIST_REMOVE_HEAD(&nm_out_filter, filter_entries); free(e); } } static int filter_insert(fn_filter filter_fn) { struct filter_entry *e; assert(filter_fn != NULL); if ((e = malloc(sizeof(struct filter_entry))) == NULL) { warn("malloc"); return (0); } e->fn = filter_fn; SLIST_INSERT_HEAD(&nm_out_filter, e, filter_entries); return (1); } static int parse_demangle_option(const char *opt) { if (opt == NULL) return (ELFTC_DEM_UNKNOWN); else if (!strncasecmp(opt, "gnu-v2", 6)) return (ELFTC_DEM_GNU2); else if (!strncasecmp(opt, "gnu-v3", 6)) return (ELFTC_DEM_GNU3); else if (!strncasecmp(opt, "arm", 3)) return (ELFTC_DEM_ARM); else errx(EXIT_FAILURE, "unknown demangling style '%s'", opt); /* NOTREACHED */ return (0); } static void get_opt(int argc, char **argv) { int ch; bool is_posix, oflag; if (argc <= 0 || argv == NULL) return; oflag = is_posix = false; nm_opts.t = RADIX_HEX; while ((ch = getopt_long(argc, argv, "ABCDF:PSVaefghlnoprst:uvx", nm_longopts, NULL)) != -1) { switch (ch) { case 'A': nm_opts.print_name = PRINT_NAME_FULL; break; case 'B': nm_opts.elem_print_fn = &sym_elem_print_all; break; case 'C': nm_opts.demangle_type = parse_demangle_option(optarg); break; case 'D': nm_opts.print_symbol = PRINT_SYM_DYN; break; case 'F': /* sysv, bsd, posix */ switch (optarg[0]) { case 'B': case 'b': nm_opts.elem_print_fn = &sym_elem_print_all; break; case 'P': case 'p': is_posix = true; nm_opts.elem_print_fn = &sym_elem_print_all_portable; break; case 'S': case 's': nm_opts.elem_print_fn = &sym_elem_print_all_sysv; break; default: warnx("%s: Invalid format", optarg); usage(1); } break; case 'P': is_posix = true; nm_opts.elem_print_fn = &sym_elem_print_all_portable; break; case 'S': nm_opts.print_size = 1; break; case 'V': print_version(); /* NOTREACHED */ case 'a': nm_opts.print_debug = true; break; case 'e': filter_insert(sym_elem_global_static); break; case 'f': break; case 'g': filter_insert(sym_elem_global); break; case 'h': usage(0); break; case 'l': nm_opts.debug_line = true; break; case 'n': case 'v': nm_opts.sort_fn = &cmp_value; break; case 'o': oflag = true; break; case 'p': nm_opts.sort_fn = &cmp_none; break; case 'r': nm_opts.sort_reverse = true; break; case 's': nm_opts.print_armap = true; break; case 't': /* t require always argument to getopt_long */ switch (optarg[0]) { case 'd': nm_opts.t = RADIX_DEC; break; case 'o': nm_opts.t = RADIX_OCT; break; case 'x': nm_opts.t = RADIX_HEX; break; default: warnx("%s: Invalid radix", optarg); usage(1); } break; case 'u': filter_insert(sym_elem_undef); nm_opts.undef_only = true; break; /* case 'v': see case 'n' above. */ case 'x': nm_opts.t = RADIX_HEX; break; case 0: if (nm_opts.sort_size != 0) { nm_opts.sort_fn = &cmp_size; filter_insert(sym_elem_def); filter_insert(sym_elem_nonzero_size); } if (nm_opts.def_only != 0) filter_insert(sym_elem_def); if (nm_opts.no_demangle != 0) nm_opts.demangle_type = -1; break; default : usage(1); } } /* * In POSIX mode, the '-o' option controls the output radix. * In non-POSIX mode, the option is a synonym for the '-A' and * '--print-file-name' options. */ if (oflag) { if (is_posix) nm_opts.t = RADIX_OCT; else nm_opts.print_name = PRINT_NAME_FULL; } assert(nm_opts.sort_fn != NULL && "nm_opts.sort_fn is null"); assert(nm_opts.elem_print_fn != NULL && "nm_opts.elem_print_fn is null"); assert(nm_opts.value_print_fn != NULL && "nm_opts.value_print_fn is null"); set_opt_value_print_fn(nm_opts.t); if (nm_opts.undef_only == true) { if (nm_opts.sort_fn == &cmp_size) errx(EXIT_FAILURE, "--size-sort with -u is meaningless"); if (nm_opts.def_only != 0) errx(EXIT_FAILURE, "-u with --defined-only is meaningless"); } if (nm_opts.print_debug == false) filter_insert(sym_elem_nondebug); if (nm_opts.sort_reverse == true && nm_opts.sort_fn == cmp_none) nm_opts.sort_reverse = false; } /* * Get symbol information from elf. */ static int get_sym(Elf *elf, struct sym_head *headp, int shnum, size_t dynndx, size_t strndx, const char *type_table, const char **sec_table, int sec_table_size) { Elf_Scn *scn; Elf_Data *data; GElf_Shdr shdr; GElf_Sym sym; struct filter_entry *fep; size_t ndx; int rtn; const char *sym_name; char type; bool filter; int i, j; assert(elf != NULL); assert(headp != NULL); rtn = 0; for (i = 1; i < shnum; i++) { if ((scn = elf_getscn(elf, i)) == NULL) { warnx("elf_getscn failed: %s", elf_errmsg(-1)); continue; } if (gelf_getshdr(scn, &shdr) != &shdr) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); continue; } if (shdr.sh_type == SHT_SYMTAB) { if (nm_opts.print_symbol != PRINT_SYM_SYM) continue; } else if (shdr.sh_type == SHT_DYNSYM) { if (nm_opts.print_symbol != PRINT_SYM_DYN) continue; } else continue; ndx = shdr.sh_type == SHT_DYNSYM ? dynndx : strndx; data = NULL; while ((data = elf_getdata(scn, data)) != NULL) { j = 1; while (gelf_getsym(data, j++, &sym) != NULL) { sym_name = get_sym_name(elf, &sym, ndx, sec_table, sec_table_size); filter = false; type = get_sym_type(&sym, type_table); SLIST_FOREACH(fep, &nm_out_filter, filter_entries) { if (!fep->fn(type, &sym, sym_name)) { filter = true; break; } } if (filter == false) { if (sym_list_insert(headp, sym_name, &sym) == 0) return (0); rtn++; } } } } return (rtn); } static const char * get_sym_name(Elf *elf, const GElf_Sym *sym, size_t ndx, const char **sec_table, int sec_table_size) { const char *sym_name; sym_name = NULL; /* Show section name as symbol name for STT_SECTION symbols. */ if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) { if (sec_table != NULL && sym->st_shndx < sec_table_size) sym_name = sec_table[sym->st_shndx]; } else sym_name = elf_strptr(elf, ndx, sym->st_name); if (sym_name == NULL) sym_name = "(null)"; return (sym_name); } static char get_sym_type(const GElf_Sym *sym, const char *type_table) { bool is_local; if (sym == NULL || type_table == NULL) return ('?'); is_local = sym->st_info >> 4 == STB_LOCAL; if (sym->st_shndx == SHN_ABS) /* absolute */ return (is_local ? 'a' : 'A'); if (sym->st_shndx == SHN_COMMON) /* common */ return ('C'); if ((sym->st_info) >> 4 == STB_WEAK) { /* weak */ if ((sym->st_info & 0xf) == STT_OBJECT) return (sym->st_shndx == SHN_UNDEF ? 'v' : 'V'); return (sym->st_shndx == SHN_UNDEF ? 'w' : 'W'); } if (sym->st_shndx == SHN_UNDEF) /* undefined */ return ('U'); return (is_local == true && type_table[sym->st_shndx] != 'N' ? tolower((unsigned char) type_table[sym->st_shndx]) : type_table[sym->st_shndx]); } static void global_dest(void) { filter_dest(); } static void global_init(void) { if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "elf_version error"); nm_info.name = ELFTC_GETPROGNAME(); nm_info.def_filename = "a.out"; nm_opts.print_symbol = PRINT_SYM_SYM; nm_opts.print_name = PRINT_NAME_NONE; nm_opts.demangle_type = -1; nm_opts.print_debug = false; nm_opts.print_armap = false; nm_opts.print_size = 0; nm_opts.debug_line = false; nm_opts.def_only = 0; nm_opts.undef_only = false; nm_opts.sort_size = 0; nm_opts.sort_reverse = false; nm_opts.no_demangle = 0; nm_opts.sort_fn = &cmp_name; nm_opts.elem_print_fn = &sym_elem_print_all; nm_opts.value_print_fn = &sym_value_dec_print; nm_opts.size_print_fn = &sym_size_dec_print; SLIST_INIT(&nm_out_filter); } static bool is_sec_data(GElf_Shdr *s) { assert(s != NULL && "shdr is NULL"); return (((s->sh_flags & SHF_ALLOC) != 0) && s->sh_type != SHT_NOBITS); } static bool is_sec_debug(const char *shname) { const char *dbg_sec[] = { ".debug", ".gnu.linkonce.wi.", ".line", ".rel.debug", ".rela.debug", ".stab", NULL }; const char **p; assert(shname != NULL && "shname is NULL"); for (p = dbg_sec; *p; p++) { if (!strncmp(shname, *p, strlen(*p))) return (true); } return (false); } static bool is_sec_nobits(GElf_Shdr *s) { assert(s != NULL && "shdr is NULL"); return (s->sh_type == SHT_NOBITS); } static bool is_sec_readonly(GElf_Shdr *s) { assert(s != NULL && "shdr is NULL"); return ((s->sh_flags & SHF_WRITE) == 0); } static bool is_sec_text(GElf_Shdr *s) { assert(s != NULL && "shdr is NULL"); return ((s->sh_flags & SHF_EXECINSTR) != 0); } static void print_ar_index(int fd, Elf *arf) { Elf *elf; Elf_Arhdr *arhdr; Elf_Arsym *arsym; Elf_Cmd cmd; off_t start; size_t arsym_size; if (arf == NULL) return; if ((arsym = elf_getarsym(arf, &arsym_size)) == NULL) return; printf("\nArchive index:\n"); start = arsym->as_off; cmd = ELF_C_READ; while (arsym_size > 1) { if (elf_rand(arf, arsym->as_off) == arsym->as_off && (elf = elf_begin(fd, cmd, arf)) != NULL) { if ((arhdr = elf_getarhdr(elf)) != NULL) printf("%s in %s\n", arsym->as_name, arhdr->ar_name != NULL ? arhdr->ar_name : arhdr->ar_rawname); elf_end(elf); } ++arsym; --arsym_size; } elf_rand(arf, start); } #define DEMANGLED_BUFFER_SIZE (8 * 1024) #define PRINT_DEMANGLED_NAME(FORMAT, NAME) do { \ char _demangled[DEMANGLED_BUFFER_SIZE]; \ if (nm_opts.demangle_type < 0 || \ elftc_demangle((NAME), _demangled, sizeof(_demangled), \ nm_opts.demangle_type) < 0) \ printf((FORMAT), (NAME)); \ else \ printf((FORMAT), _demangled); \ } while (0) static void print_header(const char *file, const char *obj) { if (file == NULL) return; if (nm_opts.elem_print_fn == &sym_elem_print_all_sysv) { printf("\n\n%s from %s", nm_opts.undef_only == false ? "Symbols" : "Undefined symbols", file); if (obj != NULL) printf("[%s]", obj); printf(":\n\n"); printf("\ Name Value Class Type Size Line Section\n\n"); } else { /* archive file without -A option and POSIX */ if (nm_opts.print_name != PRINT_NAME_FULL && obj != NULL) { if (nm_opts.elem_print_fn == sym_elem_print_all_portable) printf("%s[%s]:\n", file, obj); else if (nm_opts.elem_print_fn == sym_elem_print_all) printf("\n%s:\n", obj); /* multiple files(not archive) without -A option */ } else if (nm_opts.print_name == PRINT_NAME_MULTI) { if (nm_opts.elem_print_fn == sym_elem_print_all) printf("\n"); printf("%s:\n", file); } } } static void print_version(void) { (void) printf("%s (%s)\n", nm_info.name, elftc_version()); exit(0); } static uint64_t get_block_value(Dwarf_Debug dbg, Dwarf_Block *block) { Elf *elf; GElf_Ehdr eh; Dwarf_Error de; if (dwarf_get_elf(dbg, &elf, &de) != DW_DLV_OK) { warnx("dwarf_get_elf failed: %s", dwarf_errmsg(de)); return (0); } if (gelf_getehdr(elf, &eh) != &eh) { warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); return (0); } if (block->bl_len == 5) { if (eh.e_ident[EI_DATA] == ELFDATA2LSB) return (le32dec((uint8_t *) block->bl_data + 1)); else return (be32dec((uint8_t *) block->bl_data + 1)); } else if (block->bl_len == 9) { if (eh.e_ident[EI_DATA] == ELFDATA2LSB) return (le64dec((uint8_t *) block->bl_data + 1)); else return (be64dec((uint8_t *) block->bl_data + 1)); } return (0); } +static char * +find_object_name(Dwarf_Debug dbg, Dwarf_Die die) +{ + Dwarf_Die ret_die; + Dwarf_Attribute at; + Dwarf_Off off; + Dwarf_Error de; + const char *str; + char *name; + + if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == DW_DLV_OK) { + if ((name = strdup(str)) == NULL) { + warn("strdup"); + return (NULL); + } + return (name); + } + + if (dwarf_attr(die, DW_AT_specification, &at, &de) != DW_DLV_OK) + return (NULL); + + if (dwarf_global_formref(at, &off, &de) != DW_DLV_OK) + return (NULL); + + if (dwarf_offdie(dbg, off, &ret_die, &de) != DW_DLV_OK) + return (NULL); + + return (find_object_name(dbg, ret_die)); +} + static void search_line_attr(Dwarf_Debug dbg, struct func_info_head *func_info, struct var_info_head *var_info, Dwarf_Die die, char **src_files, Dwarf_Signed filecount) { Dwarf_Attribute at; Dwarf_Unsigned udata; Dwarf_Half tag; Dwarf_Block *block; Dwarf_Bool flag; Dwarf_Die ret_die; Dwarf_Error de; struct func_info_entry *func; struct var_info_entry *var; - const char *str; int ret; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); goto cont_search; } /* We're interested in DIEs which define functions or variables. */ if (tag != DW_TAG_subprogram && tag != DW_TAG_entry_point && tag != DW_TAG_inlined_subroutine && tag != DW_TAG_variable) goto cont_search; if (tag == DW_TAG_variable) { /* Ignore "artificial" variable. */ if (dwarf_attrval_flag(die, DW_AT_artificial, &flag, &de) == DW_DLV_OK && flag) goto cont_search; /* Ignore pure declaration. */ if (dwarf_attrval_flag(die, DW_AT_declaration, &flag, &de) == DW_DLV_OK && flag) goto cont_search; /* Ignore stack varaibles. */ if (dwarf_attrval_flag(die, DW_AT_external, &flag, &de) != DW_DLV_OK || !flag) goto cont_search; if ((var = calloc(1, sizeof(*var))) == NULL) { warn("calloc failed"); goto cont_search; } if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata, &de) == DW_DLV_OK && udata > 0 && (Dwarf_Signed) (udata - 1) < filecount) { var->file = strdup(src_files[udata - 1]); if (var->file == NULL) { warn("strdup"); free(var); goto cont_search; } } if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) == DW_DLV_OK) var->line = udata; - if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == - DW_DLV_OK) { - var->name = strdup(str); - if (var->name == NULL) { - warn("strdup"); - if (var->file) - free(var->file); - free(var); - goto cont_search; - } + var->name = find_object_name(dbg, die); + if (var->name == NULL) { + if (var->file) + free(var->file); + free(var); + goto cont_search; } if (dwarf_attr(die, DW_AT_location, &at, &de) == DW_DLV_OK && dwarf_formblock(at, &block, &de) == DW_DLV_OK) { /* * Since we ignored stack variables, the rest are the * external varaibles which should always use DW_OP_addr * operator for DW_AT_location value. */ if (*((uint8_t *)block->bl_data) == DW_OP_addr) var->addr = get_block_value(dbg, block); } SLIST_INSERT_HEAD(var_info, var, entries); } else { if ((func = calloc(1, sizeof(*func))) == NULL) { warn("calloc failed"); goto cont_search; } /* * Note that dwarf_attrval_unsigned() handles DW_AT_abstract_origin * internally, so it can retrieve DW_AT_decl_file/DW_AT_decl_line * attributes for inlined functions as well. */ if (dwarf_attrval_unsigned(die, DW_AT_decl_file, &udata, &de) == DW_DLV_OK && udata > 0 && (Dwarf_Signed) (udata - 1) < filecount) { func->file = strdup(src_files[udata - 1]); if (func->file == NULL) { warn("strdup"); free(func); goto cont_search; } } if (dwarf_attrval_unsigned(die, DW_AT_decl_line, &udata, &de) == DW_DLV_OK) func->line = udata; - if (dwarf_attrval_string(die, DW_AT_name, &str, &de) == - DW_DLV_OK) { - func->name = strdup(str); - if (func->name == NULL) { - warn("strdup"); - if (func->file) - free(func->file); - free(func); - goto cont_search; - } + func->name = find_object_name(dbg, die); + if (func->name == NULL) { + if (func->file) + free(func->file); + free(func); + goto cont_search; } if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &udata, &de) == DW_DLV_OK) func->lowpc = udata; if (dwarf_attrval_unsigned(die, DW_AT_high_pc, &udata, &de) == DW_DLV_OK) func->highpc = udata; SLIST_INSERT_HEAD(func_info, func, entries); } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_line_attr(dbg, func_info, var_info, ret_die, src_files, filecount); /* Search sibling. */ ret = dwarf_siblingof(dbg, die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_line_attr(dbg, func_info, var_info, ret_die, src_files, filecount); dwarf_dealloc(dbg, die, DW_DLA_DIE); } /* * Read elf file and collect symbol information, sort them, print. * Return 1 at failed, 0 at success. */ static int read_elf(Elf *elf, const char *filename, Elf_Kind kind) { Dwarf_Debug dbg; Dwarf_Die die; Dwarf_Error de; Dwarf_Half tag; Elf_Arhdr *arhdr; Elf_Scn *scn; GElf_Shdr shdr; GElf_Half i; Dwarf_Line *lbuf; Dwarf_Unsigned lineno; Dwarf_Signed lcount, filecount; Dwarf_Addr lineaddr; struct sym_print_data p_data; struct sym_head list_head; struct line_info_head *line_info; struct func_info_head *func_info; struct var_info_head *var_info; struct line_info_entry *lie; struct func_info_entry *func; struct var_info_entry *var; const char *shname, *objname; char *type_table, **sec_table, *sfile, **src_files; size_t shstrndx, shnum, dynndx, strndx; int ret, rtn, e_err; #define OBJNAME (objname == NULL ? filename : objname) assert(filename != NULL && "filename is null"); STAILQ_INIT(&list_head); type_table = NULL; sec_table = NULL; line_info = NULL; func_info = NULL; var_info = NULL; objname = NULL; dynndx = SHN_UNDEF; strndx = SHN_UNDEF; rtn = 0; nm_elfclass = gelf_getclass(elf); if (kind == ELF_K_AR) { if ((arhdr = elf_getarhdr(elf)) == NULL) goto next_cmd; objname = arhdr->ar_name != NULL ? arhdr->ar_name : arhdr->ar_rawname; } if (!elf_getshnum(elf, &shnum)) { if ((e_err = elf_errno()) != 0) warnx("%s: %s", OBJNAME, elf_errmsg(e_err)); else warnx("%s: cannot get section number", OBJNAME); rtn = 1; goto next_cmd; } if (shnum == 0) { warnx("%s: has no section", OBJNAME); rtn = 1; goto next_cmd; } if (!elf_getshstrndx(elf, &shstrndx)) { warnx("%s: cannot get str index", OBJNAME); rtn = 1; goto next_cmd; } /* type_table for type determine */ if ((type_table = malloc(sizeof(char) * shnum)) == NULL) { warn("%s: malloc", OBJNAME); rtn = 1; goto next_cmd; } /* sec_table for section name to display in sysv format */ if ((sec_table = calloc(shnum, sizeof(char *))) == NULL) { warn("%s: calloc", OBJNAME); rtn = 1; goto next_cmd; } type_table[0] = 'U'; if ((sec_table[0] = strdup("*UND*")) == NULL) { warn("strdup"); goto next_cmd; } for (i = 1; i < shnum; ++i) { type_table[i] = 'U'; if ((scn = elf_getscn(elf, i)) == NULL) { if ((e_err = elf_errno()) != 0) warnx("%s: %s", OBJNAME, elf_errmsg(e_err)); else warnx("%s: cannot get section", OBJNAME); rtn = 1; goto next_cmd; } if (gelf_getshdr(scn, &shdr) == NULL) goto next_cmd; /* * Cannot test by type and attribute for dynstr, strtab */ shname = elf_strptr(elf, shstrndx, (size_t) shdr.sh_name); if (shname != NULL) { if ((sec_table[i] = strdup(shname)) == NULL) { warn("strdup"); goto next_cmd; } if (!strncmp(shname, ".dynstr", 7)) { dynndx = elf_ndxscn(scn); if (dynndx == SHN_UNDEF) { warnx("%s: elf_ndxscn failed: %s", OBJNAME, elf_errmsg(-1)); goto next_cmd; } } if (!strncmp(shname, ".strtab", 7)) { strndx = elf_ndxscn(scn); if (strndx == SHN_UNDEF) { warnx("%s: elf_ndxscn failed: %s", OBJNAME, elf_errmsg(-1)); goto next_cmd; } } } else { sec_table[i] = strdup("*UND*"); if (sec_table[i] == NULL) { warn("strdup"); goto next_cmd; } } if (is_sec_text(&shdr)) type_table[i] = 'T'; else if (is_sec_data(&shdr)) { if (is_sec_readonly(&shdr)) type_table[i] = 'R'; else type_table[i] = 'D'; } else if (is_sec_nobits(&shdr)) type_table[i] = 'B'; else if (is_sec_debug(shname)) type_table[i] = 'N'; else if (is_sec_readonly(&shdr) && !is_sec_nobits(&shdr)) type_table[i] = 'n'; } print_header(filename, objname); if ((dynndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_DYN) || (strndx == SHN_UNDEF && nm_opts.print_symbol == PRINT_SYM_SYM)) { warnx("%s: no symbols", OBJNAME); /* This is not an error case */ goto next_cmd; } STAILQ_INIT(&list_head); if (!nm_opts.debug_line) goto process_sym; /* * Collect dwarf line number information. */ if (dwarf_elf_init(elf, DW_DLC_READ, NULL, NULL, &dbg, &de) != DW_DLV_OK) { warnx("dwarf_elf_init failed: %s", dwarf_errmsg(de)); goto process_sym; } line_info = malloc(sizeof(struct line_info_head)); func_info = malloc(sizeof(struct func_info_head)); var_info = malloc(sizeof(struct var_info_head)); if (line_info == NULL || func_info == NULL || var_info == NULL) { warn("malloc"); (void) dwarf_finish(dbg, &de); goto process_sym; } SLIST_INIT(line_info); SLIST_INIT(func_info); SLIST_INIT(var_info); while ((ret = dwarf_next_cu_header(dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; while (dwarf_siblingof(dbg, die, &die, &de) == DW_DLV_OK) { if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); continue; } /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } if (die == NULL) { warnx("could not find DW_TAG_compile_unit die"); continue; } /* Retrieve source file list. */ ret = dwarf_srcfiles(die, &src_files, &filecount, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_srclines: %s", dwarf_errmsg(de)); if (ret != DW_DLV_OK) continue; /* * Retrieve line number information from .debug_line section. */ ret = dwarf_srclines(die, &lbuf, &lcount, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_srclines: %s", dwarf_errmsg(de)); if (ret != DW_DLV_OK) goto line_attr; for (i = 0; (Dwarf_Signed) i < lcount; i++) { if (dwarf_lineaddr(lbuf[i], &lineaddr, &de)) { warnx("dwarf_lineaddr: %s", dwarf_errmsg(de)); continue; } if (dwarf_lineno(lbuf[i], &lineno, &de)) { warnx("dwarf_lineno: %s", dwarf_errmsg(de)); continue; } if (dwarf_linesrc(lbuf[i], &sfile, &de)) { warnx("dwarf_linesrc: %s", dwarf_errmsg(de)); continue; } if ((lie = malloc(sizeof(*lie))) == NULL) { warn("malloc"); continue; } lie->addr = lineaddr; lie->line = lineno; lie->file = strdup(sfile); if (lie->file == NULL) { warn("strdup"); free(lie); continue; } SLIST_INSERT_HEAD(line_info, lie, entries); } line_attr: /* Retrieve line number information from DIEs. */ search_line_attr(dbg, func_info, var_info, die, src_files, filecount); } (void) dwarf_finish(dbg, &de); process_sym: p_data.list_num = get_sym(elf, &list_head, shnum, dynndx, strndx, type_table, (void *) sec_table, shnum); if (p_data.list_num == 0) goto next_cmd; p_data.headp = &list_head; p_data.sh_num = shnum; p_data.t_table = type_table; p_data.s_table = (void *) sec_table; p_data.filename = filename; p_data.objname = objname; sym_list_print(&p_data, func_info, var_info, line_info); next_cmd: if (nm_opts.debug_line) { if (func_info != NULL) { while (!SLIST_EMPTY(func_info)) { func = SLIST_FIRST(func_info); SLIST_REMOVE_HEAD(func_info, entries); free(func->file); free(func->name); free(func); } free(func_info); func_info = NULL; } if (var_info != NULL) { while (!SLIST_EMPTY(var_info)) { var = SLIST_FIRST(var_info); SLIST_REMOVE_HEAD(var_info, entries); free(var->file); free(var->name); free(var); } free(var_info); var_info = NULL; } if (line_info != NULL) { while (!SLIST_EMPTY(line_info)) { lie = SLIST_FIRST(line_info); SLIST_REMOVE_HEAD(line_info, entries); free(lie->file); free(lie); } free(line_info); line_info = NULL; } } if (sec_table != NULL) for (i = 0; i < shnum; ++i) free(sec_table[i]); free(sec_table); free(type_table); sym_list_dest(&list_head); return (rtn); #undef OBJNAME } static int read_object(const char *filename) { Elf *elf, *arf; Elf_Cmd elf_cmd; Elf_Kind kind; int fd, rtn, e_err; assert(filename != NULL && "filename is null"); if ((fd = open(filename, O_RDONLY)) == -1) { warn("'%s'", filename); return (1); } elf_cmd = ELF_C_READ; if ((arf = elf_begin(fd, elf_cmd, (Elf *) NULL)) == NULL) { if ((e_err = elf_errno()) != 0) warnx("elf_begin error: %s", elf_errmsg(e_err)); else warnx("elf_begin error"); close(fd); return (1); } assert(arf != NULL && "arf is null."); rtn = 0; if ((kind = elf_kind(arf)) == ELF_K_NONE) { warnx("%s: File format not recognized", filename); elf_end(arf); close(fd); return (1); } if (kind == ELF_K_AR) { if (nm_opts.print_name == PRINT_NAME_MULTI && nm_opts.elem_print_fn == sym_elem_print_all) printf("\n%s:\n", filename); if (nm_opts.print_armap == true) print_ar_index(fd, arf); } while ((elf = elf_begin(fd, elf_cmd, arf)) != NULL) { rtn |= read_elf(elf, filename, kind); /* * If file is not archive, elf_next return ELF_C_NULL and * stop the loop. */ elf_cmd = elf_next(elf); elf_end(elf); } elf_end(arf); close(fd); return (rtn); } static int read_files(int argc, char **argv) { int rtn = 0; if (argc < 0 || argv == NULL) return (1); if (argc == 0) rtn |= read_object(nm_info.def_filename); else { if (nm_opts.print_name == PRINT_NAME_NONE && argc > 1) nm_opts.print_name = PRINT_NAME_MULTI; while (argc > 0) { rtn |= read_object(*argv); --argc; ++argv; } } return (rtn); } static void print_lineno(struct sym_entry *ep, struct func_info_head *func_info, struct var_info_head *var_info, struct line_info_head *line_info) { struct func_info_entry *func; struct var_info_entry *var; struct line_info_entry *lie; /* For function symbol, search the function line information list. */ if ((ep->sym->st_info & 0xf) == STT_FUNC && func_info != NULL) { SLIST_FOREACH(func, func_info, entries) { if (func->name != NULL && !strcmp(ep->name, func->name) && ep->sym->st_value >= func->lowpc && ep->sym->st_value < func->highpc) { printf("\t%s:%" PRIu64, func->file, func->line); return; } } } /* For variable symbol, search the variable line information list. */ if ((ep->sym->st_info & 0xf) == STT_OBJECT && var_info != NULL) { SLIST_FOREACH(var, var_info, entries) { if (!strcmp(ep->name, var->name) && ep->sym->st_value == var->addr) { printf("\t%s:%" PRIu64, var->file, var->line); return; } } } /* Otherwise search line number information the .debug_line section. */ if (line_info != NULL) { SLIST_FOREACH(lie, line_info, entries) { if (ep->sym->st_value == lie->addr) { printf("\t%s:%" PRIu64, lie->file, lie->line); return; } } } } static void set_opt_value_print_fn(enum radix t) { switch (t) { case RADIX_OCT: nm_opts.value_print_fn = &sym_value_oct_print; nm_opts.size_print_fn = &sym_size_oct_print; break; case RADIX_DEC: nm_opts.value_print_fn = &sym_value_dec_print; nm_opts.size_print_fn = &sym_size_dec_print; break; case RADIX_HEX: default : nm_opts.value_print_fn = &sym_value_hex_print; nm_opts.size_print_fn = &sym_size_hex_print; } assert(nm_opts.value_print_fn != NULL && "nm_opts.value_print_fn is null"); } static void sym_elem_print_all(char type, const char *sec, const GElf_Sym *sym, const char *name) { if (sec == NULL || sym == NULL || name == NULL || nm_opts.value_print_fn == NULL) return; if (IS_UNDEF_SYM_TYPE(type)) { if (nm_opts.t == RADIX_HEX && nm_elfclass == ELFCLASS32) printf("%-8s", ""); else printf("%-16s", ""); } else { switch ((nm_opts.sort_fn == & cmp_size ? 2 : 0) + nm_opts.print_size) { case 3: if (sym->st_size != 0) { nm_opts.value_print_fn(sym); printf(" "); nm_opts.size_print_fn(sym); } break; case 2: if (sym->st_size != 0) nm_opts.size_print_fn(sym); break; case 1: nm_opts.value_print_fn(sym); if (sym->st_size != 0) { printf(" "); nm_opts.size_print_fn(sym); } break; case 0: default: nm_opts.value_print_fn(sym); } } printf(" %c ", type); PRINT_DEMANGLED_NAME("%s", name); } static void sym_elem_print_all_portable(char type, const char *sec, const GElf_Sym *sym, const char *name) { if (sec == NULL || sym == NULL || name == NULL || nm_opts.value_print_fn == NULL) return; PRINT_DEMANGLED_NAME("%s", name); printf(" %c ", type); if (!IS_UNDEF_SYM_TYPE(type)) { nm_opts.value_print_fn(sym); printf(" "); if (sym->st_size != 0) nm_opts.size_print_fn(sym); } else printf(" "); } static void sym_elem_print_all_sysv(char type, const char *sec, const GElf_Sym *sym, const char *name) { if (sec == NULL || sym == NULL || name == NULL || nm_opts.value_print_fn == NULL) return; PRINT_DEMANGLED_NAME("%-20s|", name); if (IS_UNDEF_SYM_TYPE(type)) printf(" "); else nm_opts.value_print_fn(sym); printf("| %c |", type); switch (sym->st_info & 0xf) { case STT_OBJECT: printf("%18s|", "OBJECT"); break; case STT_FUNC: printf("%18s|", "FUNC"); break; case STT_SECTION: printf("%18s|", "SECTION"); break; case STT_FILE: printf("%18s|", "FILE"); break; case STT_LOPROC: printf("%18s|", "LOPROC"); break; case STT_HIPROC: printf("%18s|", "HIPROC"); break; case STT_NOTYPE: default: printf("%18s|", "NOTYPE"); }; if (sym->st_size != 0) nm_opts.size_print_fn(sym); else printf(" "); printf("| |%s", sec); } static int sym_elem_def(char type, const GElf_Sym *sym, const char *name) { assert(IS_SYM_TYPE((unsigned char) type)); UNUSED(sym); UNUSED(name); return (!IS_UNDEF_SYM_TYPE((unsigned char) type)); } static int sym_elem_global(char type, const GElf_Sym *sym, const char *name) { assert(IS_SYM_TYPE((unsigned char) type)); UNUSED(sym); UNUSED(name); /* weak symbols resemble global. */ return (isupper((unsigned char) type) || type == 'w'); } static int sym_elem_global_static(char type, const GElf_Sym *sym, const char *name) { unsigned char info; assert(sym != NULL); UNUSED(type); UNUSED(name); info = sym->st_info >> 4; return (info == STB_LOCAL || info == STB_GLOBAL || info == STB_WEAK); } static int sym_elem_nondebug(char type, const GElf_Sym *sym, const char *name) { assert(sym != NULL); UNUSED(type); UNUSED(name); if (sym->st_value == 0 && (sym->st_info & 0xf) == STT_FILE) return (0); if (sym->st_name == 0) return (0); return (1); } static int sym_elem_nonzero_size(char type, const GElf_Sym *sym, const char *name) { assert(sym != NULL); UNUSED(type); UNUSED(name); return (sym->st_size > 0); } static int sym_elem_undef(char type, const GElf_Sym *sym, const char *name) { assert(IS_SYM_TYPE((unsigned char) type)); UNUSED(sym); UNUSED(name); return (IS_UNDEF_SYM_TYPE((unsigned char) type)); } static void sym_list_dest(struct sym_head *headp) { struct sym_entry *ep, *ep_n; if (headp == NULL) return; ep = STAILQ_FIRST(headp); while (ep != NULL) { ep_n = STAILQ_NEXT(ep, sym_entries); free(ep->sym); free(ep->name); free(ep); ep = ep_n; } } static int sym_list_insert(struct sym_head *headp, const char *name, const GElf_Sym *sym) { struct sym_entry *e; if (headp == NULL || name == NULL || sym == NULL) return (0); if ((e = malloc(sizeof(struct sym_entry))) == NULL) { warn("malloc"); return (0); } if ((e->name = strdup(name)) == NULL) { warn("strdup"); free(e); return (0); } if ((e->sym = malloc(sizeof(GElf_Sym))) == NULL) { warn("malloc"); free(e->name); free(e); return (0); } memcpy(e->sym, sym, sizeof(GElf_Sym)); /* Display size instead of value for common symbol. */ if (sym->st_shndx == SHN_COMMON) e->sym->st_value = sym->st_size; STAILQ_INSERT_TAIL(headp, e, sym_entries); return (1); } /* If file has not .debug_info, line_info will be NULL */ static void sym_list_print(struct sym_print_data *p, struct func_info_head *func_info, struct var_info_head *var_info, struct line_info_head *line_info) { struct sym_entry *e_v; size_t si; int i; if (p == NULL || CHECK_SYM_PRINT_DATA(p)) return; if ((e_v = sym_list_sort(p)) == NULL) return; if (nm_opts.sort_reverse == false) for (si = 0; si != p->list_num; ++si) sym_list_print_each(&e_v[si], p, func_info, var_info, line_info); else for (i = p->list_num - 1; i != -1; --i) sym_list_print_each(&e_v[i], p, func_info, var_info, line_info); free(e_v); } /* If file has not .debug_info, line_info will be NULL */ static void sym_list_print_each(struct sym_entry *ep, struct sym_print_data *p, struct func_info_head *func_info, struct var_info_head *var_info, struct line_info_head *line_info) { const char *sec; char type; if (ep == NULL || CHECK_SYM_PRINT_DATA(p)) return; assert(ep->name != NULL); assert(ep->sym != NULL); type = get_sym_type(ep->sym, p->t_table); if (nm_opts.print_name == PRINT_NAME_FULL) { printf("%s", p->filename); if (nm_opts.elem_print_fn == &sym_elem_print_all_portable) { if (p->objname != NULL) printf("[%s]", p->objname); printf(": "); } else { if (p->objname != NULL) printf(":%s", p->objname); printf(":"); } } switch (ep->sym->st_shndx) { case SHN_LOPROC: /* LOPROC or LORESERVE */ sec = "*LOPROC*"; break; case SHN_HIPROC: sec = "*HIPROC*"; break; case SHN_LOOS: sec = "*LOOS*"; break; case SHN_HIOS: sec = "*HIOS*"; break; case SHN_ABS: sec = "*ABS*"; break; case SHN_COMMON: sec = "*COM*"; break; case SHN_HIRESERVE: /* HIRESERVE or XINDEX */ sec = "*HIRESERVE*"; break; default: if (ep->sym->st_shndx > p->sh_num) return; sec = p->s_table[ep->sym->st_shndx]; break; }; nm_opts.elem_print_fn(type, sec, ep->sym, ep->name); if (nm_opts.debug_line == true && !IS_UNDEF_SYM_TYPE(type)) print_lineno(ep, func_info, var_info, line_info); printf("\n"); } static struct sym_entry * sym_list_sort(struct sym_print_data *p) { struct sym_entry *ep, *e_v; int idx; if (p == NULL || CHECK_SYM_PRINT_DATA(p)) return (NULL); if ((e_v = malloc(sizeof(struct sym_entry) * p->list_num)) == NULL) { warn("malloc"); return (NULL); } idx = 0; STAILQ_FOREACH(ep, p->headp, sym_entries) { if (ep->name != NULL && ep->sym != NULL) { e_v[idx].name = ep->name; e_v[idx].sym = ep->sym; ++idx; } } assert((size_t)idx == p->list_num); if (nm_opts.sort_fn != &cmp_none) { nm_print_data = p; assert(nm_print_data != NULL); qsort(e_v, p->list_num, sizeof(struct sym_entry), nm_opts.sort_fn); } return (e_v); } static void sym_size_oct_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); printf("%016" PRIo64, sym->st_size); } static void sym_size_hex_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); if (nm_elfclass == ELFCLASS32) printf("%08" PRIx64, sym->st_size); else printf("%016" PRIx64, sym->st_size); } static void sym_size_dec_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); printf("%016" PRId64, sym->st_size); } static void sym_value_oct_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); printf("%016" PRIo64, sym->st_value); } static void sym_value_hex_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); if (nm_elfclass == ELFCLASS32) printf("%08" PRIx64, sym->st_value); else printf("%016" PRIx64, sym->st_value); } static void sym_value_dec_print(const GElf_Sym *sym) { assert(sym != NULL && "sym is null"); printf("%016" PRId64, sym->st_value); } static void usage(int exitcode) { printf("Usage: %s [options] file ...\ \n Display symbolic information in file.\n\ \n Options: \ \n -A, --print-file-name Write the full pathname or library name of an\ \n object on each line.\ \n -a, --debug-syms Display all symbols include debugger-only\ \n symbols.", nm_info.name); printf("\ \n -B Equivalent to specifying \"--format=bsd\".\ \n -C, --demangle[=style] Decode low-level symbol names.\ \n --no-demangle Do not demangle low-level symbol names.\ \n -D, --dynamic Display only dynamic symbols.\ \n -e Display only global and static symbols."); printf("\ \n -f Produce full output (default).\ \n --format=format Display output in specific format. Allowed\ \n formats are: \"bsd\", \"posix\" and \"sysv\".\ \n -g, --extern-only Display only global symbol information.\ \n -h, --help Show this help message.\ \n -l, --line-numbers Display filename and linenumber using\ \n debugging information.\ \n -n, --numeric-sort Sort symbols numerically by value."); printf("\ \n -o Write numeric values in octal. Equivalent to\ \n specifying \"-t o\".\ \n -p, --no-sort Do not sort symbols.\ \n -P Write information in a portable output format.\ \n Equivalent to specifying \"--format=posix\".\ \n -r, --reverse-sort Reverse the order of the sort.\ \n -S, --print-size Print symbol sizes instead values.\ \n -s, --print-armap Include an index of archive members.\ \n --size-sort Sort symbols by size."); printf("\ \n -t, --radix=format Write each numeric value in the specified\ \n format:\ \n d In decimal,\ \n o In octal,\ \n x In hexadecimal."); printf("\ \n -u, --undefined-only Display only undefined symbols.\ \n --defined-only Display only defined symbols.\ \n -V, --version Show the version identifier for %s.\ \n -v Sort output by value.\ \n -x Write numeric values in hexadecimal.\ \n Equivalent to specifying \"-t x\".", nm_info.name); printf("\n\ \n The default options are: output in bsd format, use a hexadecimal radix,\ \n sort by symbol name, do not demangle names.\n"); exit(exitcode); } /* * Display symbolic information in file. * Return 0 at success, >0 at failed. */ int main(int argc, char **argv) { int rtn; global_init(); get_opt(argc, argv); rtn = read_files(argc - optind, argv + optind); global_dest(); exit(rtn); } Index: head/contrib/elftoolchain/readelf/readelf.c =================================================================== --- head/contrib/elftoolchain/readelf/readelf.c (revision 280931) +++ head/contrib/elftoolchain/readelf/readelf.c (revision 280932) @@ -1,7465 +1,7468 @@ /*- * Copyright (c) 2009-2014 Kai Wang * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: readelf.c 3155 2015-02-15 19:15:57Z emaste $"); +ELFTC_VCSID("$Id: readelf.c 3178 2015-03-30 18:29:13Z emaste $"); /* * readelf(1) options. */ #define RE_AA 0x00000001 #define RE_C 0x00000002 #define RE_DD 0x00000004 #define RE_D 0x00000008 #define RE_G 0x00000010 #define RE_H 0x00000020 #define RE_II 0x00000040 #define RE_I 0x00000080 #define RE_L 0x00000100 #define RE_NN 0x00000200 #define RE_N 0x00000400 #define RE_P 0x00000800 #define RE_R 0x00001000 #define RE_SS 0x00002000 #define RE_S 0x00004000 #define RE_T 0x00008000 #define RE_U 0x00010000 #define RE_VV 0x00020000 #define RE_WW 0x00040000 #define RE_W 0x00080000 #define RE_X 0x00100000 /* * dwarf dump options. */ #define DW_A 0x00000001 #define DW_FF 0x00000002 #define DW_F 0x00000004 #define DW_I 0x00000008 #define DW_LL 0x00000010 #define DW_L 0x00000020 #define DW_M 0x00000040 #define DW_O 0x00000080 #define DW_P 0x00000100 #define DW_RR 0x00000200 #define DW_R 0x00000400 #define DW_S 0x00000800 #define DW_DEFAULT_OPTIONS (DW_A | DW_F | DW_I | DW_L | DW_O | DW_P | \ DW_R | DW_RR | DW_S) /* * readelf(1) run control flags. */ #define DISPLAY_FILENAME 0x0001 /* * Internal data structure for sections. */ struct section { const char *name; /* section name */ Elf_Scn *scn; /* section scn */ uint64_t off; /* section offset */ uint64_t sz; /* section size */ uint64_t entsize; /* section entsize */ uint64_t align; /* section alignment */ uint64_t type; /* section type */ uint64_t flags; /* section flags */ uint64_t addr; /* section virtual addr */ uint32_t link; /* section link ndx */ uint32_t info; /* section info ndx */ }; struct dumpop { union { size_t si; /* section index */ const char *sn; /* section name */ } u; enum { DUMP_BY_INDEX = 0, DUMP_BY_NAME } type; /* dump type */ #define HEX_DUMP 0x0001 #define STR_DUMP 0x0002 int op; /* dump operation */ STAILQ_ENTRY(dumpop) dumpop_list; }; struct symver { const char *name; int type; }; /* * Structure encapsulates the global data for readelf(1). */ struct readelf { const char *filename; /* current processing file. */ int options; /* command line options. */ int flags; /* run control flags. */ int dop; /* dwarf dump options. */ Elf *elf; /* underlying ELF descriptor. */ Elf *ar; /* archive ELF descriptor. */ Dwarf_Debug dbg; /* DWARF handle. */ Dwarf_Half cu_psize; /* DWARF CU pointer size. */ Dwarf_Half cu_osize; /* DWARF CU offset size. */ Dwarf_Half cu_ver; /* DWARF CU version. */ GElf_Ehdr ehdr; /* ELF header. */ int ec; /* ELF class. */ size_t shnum; /* #sections. */ struct section *vd_s; /* Verdef section. */ struct section *vn_s; /* Verneed section. */ struct section *vs_s; /* Versym section. */ uint16_t *vs; /* Versym array. */ int vs_sz; /* Versym array size. */ struct symver *ver; /* Version array. */ int ver_sz; /* Size of version array. */ struct section *sl; /* list of sections. */ STAILQ_HEAD(, dumpop) v_dumpop; /* list of dump ops. */ uint64_t (*dw_read)(Elf_Data *, uint64_t *, int); uint64_t (*dw_decode)(uint8_t **, int); }; enum options { OPTION_DEBUG_DUMP }; static struct option longopts[] = { {"all", no_argument, NULL, 'a'}, {"arch-specific", no_argument, NULL, 'A'}, {"archive-index", no_argument, NULL, 'c'}, {"debug-dump", optional_argument, NULL, OPTION_DEBUG_DUMP}, {"dynamic", no_argument, NULL, 'd'}, {"file-header", no_argument, NULL, 'h'}, {"full-section-name", no_argument, NULL, 'N'}, {"headers", no_argument, NULL, 'e'}, {"help", no_argument, 0, 'H'}, {"hex-dump", required_argument, NULL, 'x'}, {"histogram", no_argument, NULL, 'I'}, {"notes", no_argument, NULL, 'n'}, {"program-headers", no_argument, NULL, 'l'}, {"relocs", no_argument, NULL, 'r'}, {"sections", no_argument, NULL, 'S'}, {"section-headers", no_argument, NULL, 'S'}, {"section-groups", no_argument, NULL, 'g'}, {"section-details", no_argument, NULL, 't'}, {"segments", no_argument, NULL, 'l'}, {"string-dump", required_argument, NULL, 'p'}, {"symbols", no_argument, NULL, 's'}, {"syms", no_argument, NULL, 's'}, {"unwind", no_argument, NULL, 'u'}, {"use-dynamic", no_argument, NULL, 'D'}, {"version-info", no_argument, 0, 'V'}, {"version", no_argument, 0, 'v'}, {"wide", no_argument, 0, 'W'}, {NULL, 0, NULL, 0} }; struct eflags_desc { uint64_t flag; const char *desc; }; struct mips_option { uint64_t flag; const char *desc; }; static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); static const char *aeabi_adv_simd_arch(uint64_t simd); static const char *aeabi_align_needed(uint64_t an); static const char *aeabi_align_preserved(uint64_t ap); static const char *aeabi_arm_isa(uint64_t ai); static const char *aeabi_cpu_arch(uint64_t arch); static const char *aeabi_cpu_arch_profile(uint64_t pf); static const char *aeabi_div(uint64_t du); static const char *aeabi_enum_size(uint64_t es); static const char *aeabi_fp_16bit_format(uint64_t fp16); static const char *aeabi_fp_arch(uint64_t fp); static const char *aeabi_fp_denormal(uint64_t fd); static const char *aeabi_fp_exceptions(uint64_t fe); static const char *aeabi_fp_hpext(uint64_t fh); static const char *aeabi_fp_number_model(uint64_t fn); static const char *aeabi_fp_optm_goal(uint64_t fog); static const char *aeabi_fp_rounding(uint64_t fr); static const char *aeabi_hardfp(uint64_t hfp); static const char *aeabi_mpext(uint64_t mp); static const char *aeabi_optm_goal(uint64_t og); static const char *aeabi_pcs_config(uint64_t pcs); static const char *aeabi_pcs_got(uint64_t got); static const char *aeabi_pcs_r9(uint64_t r9); static const char *aeabi_pcs_ro(uint64_t ro); static const char *aeabi_pcs_rw(uint64_t rw); static const char *aeabi_pcs_wchar_t(uint64_t wt); static const char *aeabi_t2ee(uint64_t t2ee); static const char *aeabi_thumb_isa(uint64_t ti); static const char *aeabi_fp_user_exceptions(uint64_t fu); static const char *aeabi_unaligned_access(uint64_t ua); static const char *aeabi_vfp_args(uint64_t va); static const char *aeabi_virtual(uint64_t vt); static const char *aeabi_wmmx_arch(uint64_t wmmx); static const char *aeabi_wmmx_args(uint64_t wa); static const char *elf_class(unsigned int class); static const char *elf_endian(unsigned int endian); static const char *elf_machine(unsigned int mach); static const char *elf_osabi(unsigned int abi); static const char *elf_type(unsigned int type); static const char *elf_ver(unsigned int ver); static const char *dt_type(unsigned int mach, unsigned int dtype); static void dump_ar(struct readelf *re, int); static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe); static void dump_attributes(struct readelf *re); static uint8_t *dump_compatibility_tag(uint8_t *p); static void dump_dwarf(struct readelf *re); static void dump_dwarf_abbrev(struct readelf *re); static void dump_dwarf_aranges(struct readelf *re); static void dump_dwarf_block(struct readelf *re, uint8_t *b, Dwarf_Unsigned len); static void dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level); static void dump_dwarf_frame(struct readelf *re, int alt); static void dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie, uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc, Dwarf_Debug dbg); static int dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde, Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Half cie_ra); static void dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt); static void dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info); static void dump_dwarf_macinfo(struct readelf *re); static void dump_dwarf_line(struct readelf *re); static void dump_dwarf_line_decoded(struct readelf *re); static void dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr); static void dump_dwarf_loclist(struct readelf *re); static void dump_dwarf_pubnames(struct readelf *re); static void dump_dwarf_ranges(struct readelf *re); static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base); static void dump_dwarf_str(struct readelf *re); static void dump_eflags(struct readelf *re, uint64_t e_flags); static void dump_elf(struct readelf *re); static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab); static void dump_dynamic(struct readelf *re); static void dump_liblist(struct readelf *re); static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe); static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz); static void dump_mips_options(struct readelf *re, struct section *s); static void dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info); static void dump_mips_reginfo(struct readelf *re, struct section *s); static void dump_mips_specific_info(struct readelf *re); static void dump_notes(struct readelf *re); static void dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off); static void dump_svr4_hash(struct section *s); static void dump_svr4_hash64(struct readelf *re, struct section *s); static void dump_gnu_hash(struct readelf *re, struct section *s); static void dump_hash(struct readelf *re); static void dump_phdr(struct readelf *re); static void dump_ppc_attributes(uint8_t *p, uint8_t *pe); static void dump_symtab(struct readelf *re, int i); static void dump_symtabs(struct readelf *re); static uint8_t *dump_unknown_tag(uint64_t tag, uint8_t *p); static void dump_ver(struct readelf *re); static void dump_verdef(struct readelf *re, int dump); static void dump_verneed(struct readelf *re, int dump); static void dump_versym(struct readelf *re); static const char *dwarf_reg(unsigned int mach, unsigned int reg); static const char *dwarf_regname(struct readelf *re, unsigned int num); static struct dumpop *find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t); static char *get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off); static const char *get_string(struct readelf *re, int strtab, size_t off); static const char *get_symbol_name(struct readelf *re, int symtab, int i); static uint64_t get_symbol_value(struct readelf *re, int symtab, int i); static void load_sections(struct readelf *re); static const char *mips_abi_fp(uint64_t fp); static const char *note_type(const char *note_name, unsigned int et, unsigned int nt); static const char *note_type_freebsd(unsigned int nt); static const char *note_type_freebsd_core(unsigned int nt); static const char *note_type_linux_core(unsigned int nt); static const char *note_type_gnu(unsigned int nt); static const char *note_type_netbsd(unsigned int nt); static const char *note_type_openbsd(unsigned int nt); static const char *note_type_unknown(unsigned int nt); static const char *option_kind(uint8_t kind); static const char *phdr_type(unsigned int ptype); static const char *ppc_abi_fp(uint64_t fp); static const char *ppc_abi_vector(uint64_t vec); static const char *r_type(unsigned int mach, unsigned int type); static void readelf_usage(void); static void readelf_version(void); static void search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc); static void search_ver(struct readelf *re); static const char *section_type(unsigned int mach, unsigned int stype); static void set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize, Dwarf_Half ver); static const char *st_bind(unsigned int sbind); static const char *st_shndx(unsigned int shndx); static const char *st_type(unsigned int stype); static const char *st_vis(unsigned int svis); static const char *top_tag(unsigned int tag); static void unload_sections(struct readelf *re); static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read); static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read); static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read); static uint64_t _decode_msb(uint8_t **data, int bytes_to_read); static int64_t _decode_sleb128(uint8_t **dp); static uint64_t _decode_uleb128(uint8_t **dp); static struct eflags_desc arm_eflags_desc[] = { {EF_ARM_RELEXEC, "relocatable executable"}, {EF_ARM_HASENTRY, "has entry point"}, {EF_ARM_SYMSARESORTED, "sorted symbol tables"}, {EF_ARM_DYNSYMSUSESEGIDX, "dynamic symbols use segment index"}, {EF_ARM_MAPSYMSFIRST, "mapping symbols precede others"}, {EF_ARM_BE8, "BE8"}, {EF_ARM_LE8, "LE8"}, {EF_ARM_INTERWORK, "interworking enabled"}, {EF_ARM_APCS_26, "uses APCS/26"}, {EF_ARM_APCS_FLOAT, "uses APCS/float"}, {EF_ARM_PIC, "position independent"}, {EF_ARM_ALIGN8, "8 bit structure alignment"}, {EF_ARM_NEW_ABI, "uses new ABI"}, {EF_ARM_OLD_ABI, "uses old ABI"}, {EF_ARM_SOFT_FLOAT, "software FP"}, {EF_ARM_VFP_FLOAT, "VFP"}, {EF_ARM_MAVERICK_FLOAT, "Maverick FP"}, {0, NULL} }; static struct eflags_desc mips_eflags_desc[] = { {EF_MIPS_NOREORDER, "noreorder"}, {EF_MIPS_PIC, "pic"}, {EF_MIPS_CPIC, "cpic"}, {EF_MIPS_UCODE, "ugen_reserved"}, {EF_MIPS_ABI2, "abi2"}, {EF_MIPS_OPTIONS_FIRST, "odk first"}, {EF_MIPS_ARCH_ASE_MDMX, "mdmx"}, {EF_MIPS_ARCH_ASE_M16, "mips16"}, {0, NULL} }; static struct eflags_desc powerpc_eflags_desc[] = { {EF_PPC_EMB, "emb"}, {EF_PPC_RELOCATABLE, "relocatable"}, {EF_PPC_RELOCATABLE_LIB, "relocatable-lib"}, {0, NULL} }; static struct eflags_desc sparc_eflags_desc[] = { {EF_SPARC_32PLUS, "v8+"}, {EF_SPARC_SUN_US1, "ultrasparcI"}, {EF_SPARC_HAL_R1, "halr1"}, {EF_SPARC_SUN_US3, "ultrasparcIII"}, {0, NULL} }; static const char * elf_osabi(unsigned int abi) { static char s_abi[32]; switch(abi) { case ELFOSABI_SYSV: return "SYSV"; case ELFOSABI_HPUX: return "HPUS"; case ELFOSABI_NETBSD: return "NetBSD"; case ELFOSABI_GNU: return "GNU"; case ELFOSABI_HURD: return "HURD"; case ELFOSABI_86OPEN: return "86OPEN"; case ELFOSABI_SOLARIS: return "Solaris"; case ELFOSABI_AIX: return "AIX"; case ELFOSABI_IRIX: return "IRIX"; case ELFOSABI_FREEBSD: return "FreeBSD"; case ELFOSABI_TRU64: return "TRU64"; case ELFOSABI_MODESTO: return "MODESTO"; case ELFOSABI_OPENBSD: return "OpenBSD"; case ELFOSABI_OPENVMS: return "OpenVMS"; case ELFOSABI_NSK: return "NSK"; case ELFOSABI_ARM: return "ARM"; case ELFOSABI_STANDALONE: return "StandAlone"; default: snprintf(s_abi, sizeof(s_abi), "", abi); return (s_abi); } }; static const char * elf_machine(unsigned int mach) { static char s_mach[32]; switch (mach) { case EM_NONE: return "Unknown machine"; case EM_M32: return "AT&T WE32100"; case EM_SPARC: return "Sun SPARC"; case EM_386: return "Intel i386"; case EM_68K: return "Motorola 68000"; case EM_88K: return "Motorola 88000"; case EM_860: return "Intel i860"; case EM_MIPS: return "MIPS R3000 Big-Endian only"; case EM_S370: return "IBM System/370"; case EM_MIPS_RS3_LE: return "MIPS R3000 Little-Endian"; case EM_PARISC: return "HP PA-RISC"; case EM_VPP500: return "Fujitsu VPP500"; case EM_SPARC32PLUS: return "SPARC v8plus"; case EM_960: return "Intel 80960"; case EM_PPC: return "PowerPC 32-bit"; case EM_PPC64: return "PowerPC 64-bit"; case EM_S390: return "IBM System/390"; case EM_V800: return "NEC V800"; case EM_FR20: return "Fujitsu FR20"; case EM_RH32: return "TRW RH-32"; case EM_RCE: return "Motorola RCE"; case EM_ARM: return "ARM"; case EM_SH: return "Hitachi SH"; case EM_SPARCV9: return "SPARC v9 64-bit"; case EM_TRICORE: return "Siemens TriCore embedded processor"; case EM_ARC: return "Argonaut RISC Core"; case EM_H8_300: return "Hitachi H8/300"; case EM_H8_300H: return "Hitachi H8/300H"; case EM_H8S: return "Hitachi H8S"; case EM_H8_500: return "Hitachi H8/500"; case EM_IA_64: return "Intel IA-64 Processor"; case EM_MIPS_X: return "Stanford MIPS-X"; case EM_COLDFIRE: return "Motorola ColdFire"; case EM_68HC12: return "Motorola M68HC12"; case EM_MMA: return "Fujitsu MMA"; case EM_PCP: return "Siemens PCP"; case EM_NCPU: return "Sony nCPU"; case EM_NDR1: return "Denso NDR1 microprocessor"; case EM_STARCORE: return "Motorola Star*Core processor"; case EM_ME16: return "Toyota ME16 processor"; case EM_ST100: return "STMicroelectronics ST100 processor"; case EM_TINYJ: return "Advanced Logic Corp. TinyJ processor"; case EM_X86_64: return "Advanced Micro Devices x86-64"; case EM_PDSP: return "Sony DSP Processor"; case EM_FX66: return "Siemens FX66 microcontroller"; case EM_ST9PLUS: return "STMicroelectronics ST9+ 8/16 microcontroller"; case EM_ST7: return "STmicroelectronics ST7 8-bit microcontroller"; case EM_68HC16: return "Motorola MC68HC16 microcontroller"; case EM_68HC11: return "Motorola MC68HC11 microcontroller"; case EM_68HC08: return "Motorola MC68HC08 microcontroller"; case EM_68HC05: return "Motorola MC68HC05 microcontroller"; case EM_SVX: return "Silicon Graphics SVx"; case EM_ST19: return "STMicroelectronics ST19 8-bit mc"; case EM_VAX: return "Digital VAX"; case EM_CRIS: return "Axis Communications 32-bit embedded processor"; case EM_JAVELIN: return "Infineon Tech. 32bit embedded processor"; case EM_FIREPATH: return "Element 14 64-bit DSP Processor"; case EM_ZSP: return "LSI Logic 16-bit DSP Processor"; case EM_MMIX: return "Donald Knuth's educational 64-bit proc"; case EM_HUANY: return "Harvard University MI object files"; case EM_PRISM: return "SiTera Prism"; case EM_AVR: return "Atmel AVR 8-bit microcontroller"; case EM_FR30: return "Fujitsu FR30"; case EM_D10V: return "Mitsubishi D10V"; case EM_D30V: return "Mitsubishi D30V"; case EM_V850: return "NEC v850"; case EM_M32R: return "Mitsubishi M32R"; case EM_MN10300: return "Matsushita MN10300"; case EM_MN10200: return "Matsushita MN10200"; case EM_PJ: return "picoJava"; case EM_OPENRISC: return "OpenRISC 32-bit embedded processor"; case EM_ARC_A5: return "ARC Cores Tangent-A5"; case EM_XTENSA: return "Tensilica Xtensa Architecture"; case EM_VIDEOCORE: return "Alphamosaic VideoCore processor"; case EM_TMM_GPP: return "Thompson Multimedia General Purpose Processor"; case EM_NS32K: return "National Semiconductor 32000 series"; case EM_TPC: return "Tenor Network TPC processor"; case EM_SNP1K: return "Trebia SNP 1000 processor"; case EM_ST200: return "STMicroelectronics ST200 microcontroller"; case EM_IP2K: return "Ubicom IP2xxx microcontroller family"; case EM_MAX: return "MAX Processor"; case EM_CR: return "National Semiconductor CompactRISC microprocessor"; case EM_F2MC16: return "Fujitsu F2MC16"; case EM_MSP430: return "TI embedded microcontroller msp430"; case EM_BLACKFIN: return "Analog Devices Blackfin (DSP) processor"; case EM_SE_C33: return "S1C33 Family of Seiko Epson processors"; case EM_SEP: return "Sharp embedded microprocessor"; case EM_ARCA: return "Arca RISC Microprocessor"; case EM_UNICORE: return "Microprocessor series from PKU-Unity Ltd"; case EM_AARCH64: return "AArch64"; default: snprintf(s_mach, sizeof(s_mach), "", mach); return (s_mach); } } static const char * elf_class(unsigned int class) { static char s_class[32]; switch (class) { case ELFCLASSNONE: return "none"; case ELFCLASS32: return "ELF32"; case ELFCLASS64: return "ELF64"; default: snprintf(s_class, sizeof(s_class), "", class); return (s_class); } } static const char * elf_endian(unsigned int endian) { static char s_endian[32]; switch (endian) { case ELFDATANONE: return "none"; case ELFDATA2LSB: return "2's complement, little endian"; case ELFDATA2MSB: return "2's complement, big endian"; default: snprintf(s_endian, sizeof(s_endian), "", endian); return (s_endian); } } static const char * elf_type(unsigned int type) { static char s_type[32]; switch (type) { case ET_NONE: return "NONE (None)"; case ET_REL: return "REL (Relocatable file)"; case ET_EXEC: return "EXEC (Executable file)"; case ET_DYN: return "DYN (Shared object file)"; case ET_CORE: return "CORE (Core file)"; default: if (type >= ET_LOPROC) snprintf(s_type, sizeof(s_type), "", type); else if (type >= ET_LOOS && type <= ET_HIOS) snprintf(s_type, sizeof(s_type), "", type); else snprintf(s_type, sizeof(s_type), "", type); return (s_type); } } static const char * elf_ver(unsigned int ver) { static char s_ver[32]; switch (ver) { case EV_CURRENT: return "(current)"; case EV_NONE: return "(none)"; default: snprintf(s_ver, sizeof(s_ver), "", ver); return (s_ver); } } static const char * phdr_type(unsigned int ptype) { static char s_ptype[32]; switch (ptype) { case PT_NULL: return "NULL"; case PT_LOAD: return "LOAD"; case PT_DYNAMIC: return "DYNAMIC"; case PT_INTERP: return "INTERP"; case PT_NOTE: return "NOTE"; case PT_SHLIB: return "SHLIB"; case PT_PHDR: return "PHDR"; case PT_TLS: return "TLS"; case PT_GNU_EH_FRAME: return "GNU_EH_FRAME"; case PT_GNU_STACK: return "GNU_STACK"; case PT_GNU_RELRO: return "GNU_RELRO"; default: if (ptype >= PT_LOPROC && ptype <= PT_HIPROC) snprintf(s_ptype, sizeof(s_ptype), "LOPROC+%#x", ptype - PT_LOPROC); else if (ptype >= PT_LOOS && ptype <= PT_HIOS) snprintf(s_ptype, sizeof(s_ptype), "LOOS+%#x", ptype - PT_LOOS); else snprintf(s_ptype, sizeof(s_ptype), "", ptype); return (s_ptype); } } static const char * section_type(unsigned int mach, unsigned int stype) { static char s_stype[32]; if (stype >= SHT_LOPROC && stype <= SHT_HIPROC) { switch (mach) { case EM_X86_64: switch (stype) { case SHT_AMD64_UNWIND: return "AMD64_UNWIND"; default: break; } break; case EM_MIPS: case EM_MIPS_RS3_LE: switch (stype) { case SHT_MIPS_LIBLIST: return "MIPS_LIBLIST"; case SHT_MIPS_MSYM: return "MIPS_MSYM"; case SHT_MIPS_CONFLICT: return "MIPS_CONFLICT"; case SHT_MIPS_GPTAB: return "MIPS_GPTAB"; case SHT_MIPS_UCODE: return "MIPS_UCODE"; case SHT_MIPS_DEBUG: return "MIPS_DEBUG"; case SHT_MIPS_REGINFO: return "MIPS_REGINFO"; case SHT_MIPS_PACKAGE: return "MIPS_PACKAGE"; case SHT_MIPS_PACKSYM: return "MIPS_PACKSYM"; case SHT_MIPS_RELD: return "MIPS_RELD"; case SHT_MIPS_IFACE: return "MIPS_IFACE"; case SHT_MIPS_CONTENT: return "MIPS_CONTENT"; case SHT_MIPS_OPTIONS: return "MIPS_OPTIONS"; case SHT_MIPS_DELTASYM: return "MIPS_DELTASYM"; case SHT_MIPS_DELTAINST: return "MIPS_DELTAINST"; case SHT_MIPS_DELTACLASS: return "MIPS_DELTACLASS"; case SHT_MIPS_DWARF: return "MIPS_DWARF"; case SHT_MIPS_DELTADECL: return "MIPS_DELTADECL"; case SHT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; case SHT_MIPS_EVENTS: return "MIPS_EVENTS"; case SHT_MIPS_TRANSLATE: return "MIPS_TRANSLATE"; case SHT_MIPS_PIXIE: return "MIPS_PIXIE"; case SHT_MIPS_XLATE: return "MIPS_XLATE"; case SHT_MIPS_XLATE_DEBUG: return "MIPS_XLATE_DEBUG"; case SHT_MIPS_WHIRL: return "MIPS_WHIRL"; case SHT_MIPS_EH_REGION: return "MIPS_EH_REGION"; case SHT_MIPS_XLATE_OLD: return "MIPS_XLATE_OLD"; case SHT_MIPS_PDR_EXCEPTION: return "MIPS_PDR_EXCEPTION"; default: break; } break; default: break; } snprintf(s_stype, sizeof(s_stype), "LOPROC+%#x", stype - SHT_LOPROC); return (s_stype); } switch (stype) { case SHT_NULL: return "NULL"; case SHT_PROGBITS: return "PROGBITS"; case SHT_SYMTAB: return "SYMTAB"; case SHT_STRTAB: return "STRTAB"; case SHT_RELA: return "RELA"; case SHT_HASH: return "HASH"; case SHT_DYNAMIC: return "DYNAMIC"; case SHT_NOTE: return "NOTE"; case SHT_NOBITS: return "NOBITS"; case SHT_REL: return "REL"; case SHT_SHLIB: return "SHLIB"; case SHT_DYNSYM: return "DYNSYM"; case SHT_INIT_ARRAY: return "INIT_ARRAY"; case SHT_FINI_ARRAY: return "FINI_ARRAY"; case SHT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case SHT_GROUP: return "GROUP"; case SHT_SYMTAB_SHNDX: return "SYMTAB_SHNDX"; case SHT_SUNW_dof: return "SUNW_dof"; case SHT_SUNW_cap: return "SUNW_cap"; case SHT_GNU_HASH: return "GNU_HASH"; case SHT_SUNW_ANNOTATE: return "SUNW_ANNOTATE"; case SHT_SUNW_DEBUGSTR: return "SUNW_DEBUGSTR"; case SHT_SUNW_DEBUG: return "SUNW_DEBUG"; case SHT_SUNW_move: return "SUNW_move"; case SHT_SUNW_COMDAT: return "SUNW_COMDAT"; case SHT_SUNW_syminfo: return "SUNW_syminfo"; case SHT_SUNW_verdef: return "SUNW_verdef"; case SHT_SUNW_verneed: return "SUNW_verneed"; case SHT_SUNW_versym: return "SUNW_versym"; default: if (stype >= SHT_LOOS && stype <= SHT_HIOS) snprintf(s_stype, sizeof(s_stype), "LOOS+%#x", stype - SHT_LOOS); else if (stype >= SHT_LOUSER) snprintf(s_stype, sizeof(s_stype), "LOUSER+%#x", stype - SHT_LOUSER); else snprintf(s_stype, sizeof(s_stype), "", stype); return (s_stype); } } static const char * dt_type(unsigned int mach, unsigned int dtype) { static char s_dtype[32]; if (dtype >= DT_LOPROC && dtype <= DT_HIPROC) { switch (mach) { case EM_ARM: switch (dtype) { case DT_ARM_SYMTABSZ: return "ARM_SYMTABSZ"; default: break; } break; case EM_MIPS: case EM_MIPS_RS3_LE: switch (dtype) { case DT_MIPS_RLD_VERSION: return "MIPS_RLD_VERSION"; case DT_MIPS_TIME_STAMP: return "MIPS_TIME_STAMP"; case DT_MIPS_ICHECKSUM: return "MIPS_ICHECKSUM"; case DT_MIPS_IVERSION: return "MIPS_IVERSION"; case DT_MIPS_FLAGS: return "MIPS_FLAGS"; case DT_MIPS_BASE_ADDRESS: return "MIPS_BASE_ADDRESS"; case DT_MIPS_CONFLICT: return "MIPS_CONFLICT"; case DT_MIPS_LIBLIST: return "MIPS_LIBLIST"; case DT_MIPS_LOCAL_GOTNO: return "MIPS_LOCAL_GOTNO"; case DT_MIPS_CONFLICTNO: return "MIPS_CONFLICTNO"; case DT_MIPS_LIBLISTNO: return "MIPS_LIBLISTNO"; case DT_MIPS_SYMTABNO: return "MIPS_SYMTABNO"; case DT_MIPS_UNREFEXTNO: return "MIPS_UNREFEXTNO"; case DT_MIPS_GOTSYM: return "MIPS_GOTSYM"; case DT_MIPS_HIPAGENO: return "MIPS_HIPAGENO"; case DT_MIPS_RLD_MAP: return "MIPS_RLD_MAP"; case DT_MIPS_DELTA_CLASS: return "MIPS_DELTA_CLASS"; case DT_MIPS_DELTA_CLASS_NO: return "MIPS_DELTA_CLASS_NO"; case DT_MIPS_DELTA_INSTANCE: return "MIPS_DELTA_INSTANCE"; case DT_MIPS_DELTA_INSTANCE_NO: return "MIPS_DELTA_INSTANCE_NO"; case DT_MIPS_DELTA_RELOC: return "MIPS_DELTA_RELOC"; case DT_MIPS_DELTA_RELOC_NO: return "MIPS_DELTA_RELOC_NO"; case DT_MIPS_DELTA_SYM: return "MIPS_DELTA_SYM"; case DT_MIPS_DELTA_SYM_NO: return "MIPS_DELTA_SYM_NO"; case DT_MIPS_DELTA_CLASSSYM: return "MIPS_DELTA_CLASSSYM"; case DT_MIPS_DELTA_CLASSSYM_NO: return "MIPS_DELTA_CLASSSYM_NO"; case DT_MIPS_CXX_FLAGS: return "MIPS_CXX_FLAGS"; case DT_MIPS_PIXIE_INIT: return "MIPS_PIXIE_INIT"; case DT_MIPS_SYMBOL_LIB: return "MIPS_SYMBOL_LIB"; case DT_MIPS_LOCALPAGE_GOTIDX: return "MIPS_LOCALPAGE_GOTIDX"; case DT_MIPS_LOCAL_GOTIDX: return "MIPS_LOCAL_GOTIDX"; case DT_MIPS_HIDDEN_GOTIDX: return "MIPS_HIDDEN_GOTIDX"; case DT_MIPS_PROTECTED_GOTIDX: return "MIPS_PROTECTED_GOTIDX"; case DT_MIPS_OPTIONS: return "MIPS_OPTIONS"; case DT_MIPS_INTERFACE: return "MIPS_INTERFACE"; case DT_MIPS_DYNSTR_ALIGN: return "MIPS_DYNSTR_ALIGN"; case DT_MIPS_INTERFACE_SIZE: return "MIPS_INTERFACE_SIZE"; case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: return "MIPS_RLD_TEXT_RESOLVE_ADDR"; case DT_MIPS_PERF_SUFFIX: return "MIPS_PERF_SUFFIX"; case DT_MIPS_COMPACT_SIZE: return "MIPS_COMPACT_SIZE"; case DT_MIPS_GP_VALUE: return "MIPS_GP_VALUE"; case DT_MIPS_AUX_DYNAMIC: return "MIPS_AUX_DYNAMIC"; case DT_MIPS_PLTGOT: return "MIPS_PLTGOT"; case DT_MIPS_RLD_OBJ_UPDATE: return "MIPS_RLD_OBJ_UPDATE"; case DT_MIPS_RWPLT: return "MIPS_RWPLT"; default: break; } break; case EM_SPARC: case EM_SPARC32PLUS: case EM_SPARCV9: switch (dtype) { case DT_SPARC_REGISTER: return "DT_SPARC_REGISTER"; default: break; } break; default: break; } snprintf(s_dtype, sizeof(s_dtype), "", dtype); return (s_dtype); } switch (dtype) { case DT_NULL: return "NULL"; case DT_NEEDED: return "NEEDED"; case DT_PLTRELSZ: return "PLTRELSZ"; case DT_PLTGOT: return "PLTGOT"; case DT_HASH: return "HASH"; case DT_STRTAB: return "STRTAB"; case DT_SYMTAB: return "SYMTAB"; case DT_RELA: return "RELA"; case DT_RELASZ: return "RELASZ"; case DT_RELAENT: return "RELAENT"; case DT_STRSZ: return "STRSZ"; case DT_SYMENT: return "SYMENT"; case DT_INIT: return "INIT"; case DT_FINI: return "FINI"; case DT_SONAME: return "SONAME"; case DT_RPATH: return "RPATH"; case DT_SYMBOLIC: return "SYMBOLIC"; case DT_REL: return "REL"; case DT_RELSZ: return "RELSZ"; case DT_RELENT: return "RELENT"; case DT_PLTREL: return "PLTREL"; case DT_DEBUG: return "DEBUG"; case DT_TEXTREL: return "TEXTREL"; case DT_JMPREL: return "JMPREL"; case DT_BIND_NOW: return "BIND_NOW"; case DT_INIT_ARRAY: return "INIT_ARRAY"; case DT_FINI_ARRAY: return "FINI_ARRAY"; case DT_INIT_ARRAYSZ: return "INIT_ARRAYSZ"; case DT_FINI_ARRAYSZ: return "FINI_ARRAYSZ"; case DT_RUNPATH: return "RUNPATH"; case DT_FLAGS: return "FLAGS"; case DT_PREINIT_ARRAY: return "PREINIT_ARRAY"; case DT_PREINIT_ARRAYSZ: return "PREINIT_ARRAYSZ"; case DT_MAXPOSTAGS: return "MAXPOSTAGS"; case DT_SUNW_AUXILIARY: return "SUNW_AUXILIARY"; case DT_SUNW_RTLDINF: return "SUNW_RTLDINF"; case DT_SUNW_FILTER: return "SUNW_FILTER"; case DT_SUNW_CAP: return "SUNW_CAP"; case DT_CHECKSUM: return "CHECKSUM"; case DT_PLTPADSZ: return "PLTPADSZ"; case DT_MOVEENT: return "MOVEENT"; case DT_MOVESZ: return "MOVESZ"; case DT_FEATURE: return "FEATURE"; case DT_POSFLAG_1: return "POSFLAG_1"; case DT_SYMINSZ: return "SYMINSZ"; case DT_SYMINENT: return "SYMINENT"; case DT_GNU_HASH: return "GNU_HASH"; case DT_GNU_CONFLICT: return "GNU_CONFLICT"; case DT_GNU_LIBLIST: return "GNU_LIBLIST"; case DT_CONFIG: return "CONFIG"; case DT_DEPAUDIT: return "DEPAUDIT"; case DT_AUDIT: return "AUDIT"; case DT_PLTPAD: return "PLTPAD"; case DT_MOVETAB: return "MOVETAB"; case DT_SYMINFO: return "SYMINFO"; case DT_VERSYM: return "VERSYM"; case DT_RELACOUNT: return "RELACOUNT"; case DT_RELCOUNT: return "RELCOUNT"; case DT_FLAGS_1: return "FLAGS_1"; case DT_VERDEF: return "VERDEF"; case DT_VERDEFNUM: return "VERDEFNUM"; case DT_VERNEED: return "VERNEED"; case DT_VERNEEDNUM: return "VERNEEDNUM"; case DT_AUXILIARY: return "AUXILIARY"; case DT_USED: return "USED"; case DT_FILTER: return "FILTER"; case DT_GNU_PRELINKED: return "GNU_PRELINKED"; case DT_GNU_CONFLICTSZ: return "GNU_CONFLICTSZ"; case DT_GNU_LIBLISTSZ: return "GNU_LIBLISTSZ"; default: snprintf(s_dtype, sizeof(s_dtype), "", dtype); return (s_dtype); } } static const char * st_bind(unsigned int sbind) { static char s_sbind[32]; switch (sbind) { case STB_LOCAL: return "LOCAL"; case STB_GLOBAL: return "GLOBAL"; case STB_WEAK: return "WEAK"; default: if (sbind >= STB_LOOS && sbind <= STB_HIOS) return "OS"; else if (sbind >= STB_LOPROC && sbind <= STB_HIPROC) return "PROC"; else snprintf(s_sbind, sizeof(s_sbind), "", sbind); return (s_sbind); } } static const char * st_type(unsigned int stype) { static char s_stype[32]; switch (stype) { case STT_NOTYPE: return "NOTYPE"; case STT_OBJECT: return "OBJECT"; case STT_FUNC: return "FUNC"; case STT_SECTION: return "SECTION"; case STT_FILE: return "FILE"; case STT_COMMON: return "COMMON"; case STT_TLS: return "TLS"; default: if (stype >= STT_LOOS && stype <= STT_HIOS) snprintf(s_stype, sizeof(s_stype), "OS+%#x", stype - STT_LOOS); else if (stype >= STT_LOPROC && stype <= STT_HIPROC) snprintf(s_stype, sizeof(s_stype), "PROC+%#x", stype - STT_LOPROC); else snprintf(s_stype, sizeof(s_stype), "", stype); return (s_stype); } } static const char * st_vis(unsigned int svis) { static char s_svis[32]; switch(svis) { case STV_DEFAULT: return "DEFAULT"; case STV_INTERNAL: return "INTERNAL"; case STV_HIDDEN: return "HIDDEN"; case STV_PROTECTED: return "PROTECTED"; default: snprintf(s_svis, sizeof(s_svis), "", svis); return (s_svis); } } static const char * st_shndx(unsigned int shndx) { static char s_shndx[32]; switch (shndx) { case SHN_UNDEF: return "UND"; case SHN_ABS: return "ABS"; case SHN_COMMON: return "COM"; default: if (shndx >= SHN_LOPROC && shndx <= SHN_HIPROC) return "PRC"; else if (shndx >= SHN_LOOS && shndx <= SHN_HIOS) return "OS"; else snprintf(s_shndx, sizeof(s_shndx), "%u", shndx); return (s_shndx); } } static struct { const char *ln; char sn; int value; } section_flag[] = { {"WRITE", 'W', SHF_WRITE}, {"ALLOC", 'A', SHF_ALLOC}, {"EXEC", 'X', SHF_EXECINSTR}, {"MERGE", 'M', SHF_MERGE}, {"STRINGS", 'S', SHF_STRINGS}, {"INFO LINK", 'I', SHF_INFO_LINK}, {"OS NONCONF", 'O', SHF_OS_NONCONFORMING}, {"GROUP", 'G', SHF_GROUP}, {"TLS", 'T', SHF_TLS}, {NULL, 0, 0} }; static const char * r_type(unsigned int mach, unsigned int type) { switch(mach) { case EM_NONE: return ""; case EM_386: switch(type) { case 0: return "R_386_NONE"; case 1: return "R_386_32"; case 2: return "R_386_PC32"; case 3: return "R_386_GOT32"; case 4: return "R_386_PLT32"; case 5: return "R_386_COPY"; case 6: return "R_386_GLOB_DAT"; case 7: return "R_386_JMP_SLOT"; case 8: return "R_386_RELATIVE"; case 9: return "R_386_GOTOFF"; case 10: return "R_386_GOTPC"; case 14: return "R_386_TLS_TPOFF"; case 15: return "R_386_TLS_IE"; case 16: return "R_386_TLS_GOTIE"; case 17: return "R_386_TLS_LE"; case 18: return "R_386_TLS_GD"; case 19: return "R_386_TLS_LDM"; case 24: return "R_386_TLS_GD_32"; case 25: return "R_386_TLS_GD_PUSH"; case 26: return "R_386_TLS_GD_CALL"; case 27: return "R_386_TLS_GD_POP"; case 28: return "R_386_TLS_LDM_32"; case 29: return "R_386_TLS_LDM_PUSH"; case 30: return "R_386_TLS_LDM_CALL"; case 31: return "R_386_TLS_LDM_POP"; case 32: return "R_386_TLS_LDO_32"; case 33: return "R_386_TLS_IE_32"; case 34: return "R_386_TLS_LE_32"; case 35: return "R_386_TLS_DTPMOD32"; case 36: return "R_386_TLS_DTPOFF32"; case 37: return "R_386_TLS_TPOFF32"; default: return ""; } case EM_AARCH64: switch(type) { case 0: return "R_AARCH64_NONE"; case 257: return "R_AARCH64_ABS64"; case 258: return "R_AARCH64_ABS32"; case 259: return "R_AARCH64_ABS16"; case 260: return "R_AARCH64_PREL64"; case 261: return "R_AARCH64_PREL32"; case 262: return "R_AARCH64_PREL16"; case 263: return "R_AARCH64_MOVW_UABS_G0"; case 264: return "R_AARCH64_MOVW_UABS_G0_NC"; case 265: return "R_AARCH64_MOVW_UABS_G1"; case 266: return "R_AARCH64_MOVW_UABS_G1_NC"; case 267: return "R_AARCH64_MOVW_UABS_G2"; case 268: return "R_AARCH64_MOVW_UABS_G2_NC"; case 269: return "R_AARCH64_MOVW_UABS_G3"; case 270: return "R_AARCH64_MOVW_SABS_G0"; case 271: return "R_AARCH64_MOVW_SABS_G1"; case 272: return "R_AARCH64_MOVW_SABS_G2"; case 273: return "R_AARCH64_LD_PREL_LO19"; case 274: return "R_AARCH64_ADR_PREL_LO21"; case 275: return "R_AARCH64_ADR_PREL_PG_HI21"; case 276: return "R_AARCH64_ADR_PREL_PG_HI21_NC"; case 277: return "R_AARCH64_ADD_ABS_LO12_NC"; case 278: return "R_AARCH64_LDST8_ABS_LO12_NC"; case 279: return "R_AARCH64_TSTBR14"; case 280: return "R_AARCH64_CONDBR19"; case 282: return "R_AARCH64_JUMP26"; case 283: return "R_AARCH64_CALL26"; case 284: return "R_AARCH64_LDST16_ABS_LO12_NC"; case 285: return "R_AARCH64_LDST32_ABS_LO12_NC"; case 286: return "R_AARCH64_LDST64_ABS_LO12_NC"; case 287: return "R_AARCH64_MOVW_PREL_G0"; case 288: return "R_AARCH64_MOVW_PREL_G0_NC"; case 289: return "R_AARCH64_MOVW_PREL_G1"; case 290: return "R_AARCH64_MOVW_PREL_G1_NC"; case 291: return "R_AARCH64_MOVW_PREL_G2"; case 292: return "R_AARCH64_MOVW_PREL_G2_NC"; case 293: return "R_AARCH64_MOVW_PREL_G3"; case 299: return "R_AARCH64_LDST128_ABS_LO12_NC"; case 300: return "R_AARCH64_MOVW_GOTOFF_G0"; case 301: return "R_AARCH64_MOVW_GOTOFF_G0_NC"; case 302: return "R_AARCH64_MOVW_GOTOFF_G1"; case 303: return "R_AARCH64_MOVW_GOTOFF_G1_NC"; case 304: return "R_AARCH64_MOVW_GOTOFF_G2"; case 305: return "R_AARCH64_MOVW_GOTOFF_G2_NC"; case 306: return "R_AARCH64_MOVW_GOTOFF_G3"; case 307: return "R_AARCH64_GOTREL64"; case 308: return "R_AARCH64_GOTREL32"; case 309: return "R_AARCH64_GOT_LD_PREL19"; case 310: return "R_AARCH64_LD64_GOTOFF_LO15"; case 311: return "R_AARCH64_ADR_GOT_PAGE"; case 312: return "R_AARCH64_LD64_GOT_LO12_NC"; case 313: return "R_AARCH64_LD64_GOTPAGE_LO15"; case 1024: return "R_AARCH64_COPY"; case 1025: return "R_AARCH64_GLOB_DAT"; case 1026: return "R_AARCH64_JUMP_SLOT"; case 1027: return "R_AARCH64_RELATIVE"; + case 1028: return "R_AARCH64_TLS_DTPREL64"; + case 1029: return "R_AARCH64_TLS_DTPMOD64"; + case 1030: return "R_AARCH64_TLS_TPREL64"; case 1031: return "R_AARCH64_TLSDESC"; + case 1032: return "R_AARCH64_IRELATIVE"; default: return ""; } case EM_ARM: switch(type) { case 0: return "R_ARM_NONE"; case 1: return "R_ARM_PC24"; case 2: return "R_ARM_ABS32"; case 3: return "R_ARM_REL32"; case 4: return "R_ARM_PC13"; case 5: return "R_ARM_ABS16"; case 6: return "R_ARM_ABS12"; case 7: return "R_ARM_THM_ABS5"; case 8: return "R_ARM_ABS8"; case 9: return "R_ARM_SBREL32"; case 10: return "R_ARM_THM_PC22"; case 11: return "R_ARM_THM_PC8"; case 12: return "R_ARM_AMP_VCALL9"; case 13: return "R_ARM_SWI24"; case 14: return "R_ARM_THM_SWI8"; case 15: return "R_ARM_XPC25"; case 16: return "R_ARM_THM_XPC22"; case 20: return "R_ARM_COPY"; case 21: return "R_ARM_GLOB_DAT"; case 22: return "R_ARM_JUMP_SLOT"; case 23: return "R_ARM_RELATIVE"; case 24: return "R_ARM_GOTOFF"; case 25: return "R_ARM_GOTPC"; case 26: return "R_ARM_GOT32"; case 27: return "R_ARM_PLT32"; case 100: return "R_ARM_GNU_VTENTRY"; case 101: return "R_ARM_GNU_VTINHERIT"; case 250: return "R_ARM_RSBREL32"; case 251: return "R_ARM_THM_RPC22"; case 252: return "R_ARM_RREL32"; case 253: return "R_ARM_RABS32"; case 254: return "R_ARM_RPC24"; case 255: return "R_ARM_RBASE"; default: return ""; } case EM_IA_64: switch(type) { case 0: return "R_IA_64_NONE"; case 33: return "R_IA_64_IMM14"; case 34: return "R_IA_64_IMM22"; case 35: return "R_IA_64_IMM64"; case 36: return "R_IA_64_DIR32MSB"; case 37: return "R_IA_64_DIR32LSB"; case 38: return "R_IA_64_DIR64MSB"; case 39: return "R_IA_64_DIR64LSB"; case 42: return "R_IA_64_GPREL22"; case 43: return "R_IA_64_GPREL64I"; case 44: return "R_IA_64_GPREL32MSB"; case 45: return "R_IA_64_GPREL32LSB"; case 46: return "R_IA_64_GPREL64MSB"; case 47: return "R_IA_64_GPREL64LSB"; case 50: return "R_IA_64_LTOFF22"; case 51: return "R_IA_64_LTOFF64I"; case 58: return "R_IA_64_PLTOFF22"; case 59: return "R_IA_64_PLTOFF64I"; case 62: return "R_IA_64_PLTOFF64MSB"; case 63: return "R_IA_64_PLTOFF64LSB"; case 67: return "R_IA_64_FPTR64I"; case 68: return "R_IA_64_FPTR32MSB"; case 69: return "R_IA_64_FPTR32LSB"; case 70: return "R_IA_64_FPTR64MSB"; case 71: return "R_IA_64_FPTR64LSB"; case 72: return "R_IA_64_PCREL60B"; case 73: return "R_IA_64_PCREL21B"; case 74: return "R_IA_64_PCREL21M"; case 75: return "R_IA_64_PCREL21F"; case 76: return "R_IA_64_PCREL32MSB"; case 77: return "R_IA_64_PCREL32LSB"; case 78: return "R_IA_64_PCREL64MSB"; case 79: return "R_IA_64_PCREL64LSB"; case 82: return "R_IA_64_LTOFF_FPTR22"; case 83: return "R_IA_64_LTOFF_FPTR64I"; case 84: return "R_IA_64_LTOFF_FPTR32MSB"; case 85: return "R_IA_64_LTOFF_FPTR32LSB"; case 86: return "R_IA_64_LTOFF_FPTR64MSB"; case 87: return "R_IA_64_LTOFF_FPTR64LSB"; case 92: return "R_IA_64_SEGREL32MSB"; case 93: return "R_IA_64_SEGREL32LSB"; case 94: return "R_IA_64_SEGREL64MSB"; case 95: return "R_IA_64_SEGREL64LSB"; case 100: return "R_IA_64_SECREL32MSB"; case 101: return "R_IA_64_SECREL32LSB"; case 102: return "R_IA_64_SECREL64MSB"; case 103: return "R_IA_64_SECREL64LSB"; case 108: return "R_IA_64_REL32MSB"; case 109: return "R_IA_64_REL32LSB"; case 110: return "R_IA_64_REL64MSB"; case 111: return "R_IA_64_REL64LSB"; case 116: return "R_IA_64_LTV32MSB"; case 117: return "R_IA_64_LTV32LSB"; case 118: return "R_IA_64_LTV64MSB"; case 119: return "R_IA_64_LTV64LSB"; case 121: return "R_IA_64_PCREL21BI"; case 122: return "R_IA_64_PCREL22"; case 123: return "R_IA_64_PCREL64I"; case 128: return "R_IA_64_IPLTMSB"; case 129: return "R_IA_64_IPLTLSB"; case 133: return "R_IA_64_SUB"; case 134: return "R_IA_64_LTOFF22X"; case 135: return "R_IA_64_LDXMOV"; case 145: return "R_IA_64_TPREL14"; case 146: return "R_IA_64_TPREL22"; case 147: return "R_IA_64_TPREL64I"; case 150: return "R_IA_64_TPREL64MSB"; case 151: return "R_IA_64_TPREL64LSB"; case 154: return "R_IA_64_LTOFF_TPREL22"; case 166: return "R_IA_64_DTPMOD64MSB"; case 167: return "R_IA_64_DTPMOD64LSB"; case 170: return "R_IA_64_LTOFF_DTPMOD22"; case 177: return "R_IA_64_DTPREL14"; case 178: return "R_IA_64_DTPREL22"; case 179: return "R_IA_64_DTPREL64I"; case 180: return "R_IA_64_DTPREL32MSB"; case 181: return "R_IA_64_DTPREL32LSB"; case 182: return "R_IA_64_DTPREL64MSB"; case 183: return "R_IA_64_DTPREL64LSB"; case 186: return "R_IA_64_LTOFF_DTPREL22"; default: return ""; } case EM_MIPS: switch(type) { case 0: return "R_MIPS_NONE"; case 1: return "R_MIPS_16"; case 2: return "R_MIPS_32"; case 3: return "R_MIPS_REL32"; case 4: return "R_MIPS_26"; case 5: return "R_MIPS_HI16"; case 6: return "R_MIPS_LO16"; case 7: return "R_MIPS_GPREL16"; case 8: return "R_MIPS_LITERAL"; case 9: return "R_MIPS_GOT16"; case 10: return "R_MIPS_PC16"; case 11: return "R_MIPS_CALL16"; case 12: return "R_MIPS_GPREL32"; case 21: return "R_MIPS_GOTHI16"; case 22: return "R_MIPS_GOTLO16"; case 30: return "R_MIPS_CALLHI16"; case 31: return "R_MIPS_CALLLO16"; default: return ""; } case EM_PPC: switch(type) { case 0: return "R_PPC_NONE"; case 1: return "R_PPC_ADDR32"; case 2: return "R_PPC_ADDR24"; case 3: return "R_PPC_ADDR16"; case 4: return "R_PPC_ADDR16_LO"; case 5: return "R_PPC_ADDR16_HI"; case 6: return "R_PPC_ADDR16_HA"; case 7: return "R_PPC_ADDR14"; case 8: return "R_PPC_ADDR14_BRTAKEN"; case 9: return "R_PPC_ADDR14_BRNTAKEN"; case 10: return "R_PPC_REL24"; case 11: return "R_PPC_REL14"; case 12: return "R_PPC_REL14_BRTAKEN"; case 13: return "R_PPC_REL14_BRNTAKEN"; case 14: return "R_PPC_GOT16"; case 15: return "R_PPC_GOT16_LO"; case 16: return "R_PPC_GOT16_HI"; case 17: return "R_PPC_GOT16_HA"; case 18: return "R_PPC_PLTREL24"; case 19: return "R_PPC_COPY"; case 20: return "R_PPC_GLOB_DAT"; case 21: return "R_PPC_JMP_SLOT"; case 22: return "R_PPC_RELATIVE"; case 23: return "R_PPC_LOCAL24PC"; case 24: return "R_PPC_UADDR32"; case 25: return "R_PPC_UADDR16"; case 26: return "R_PPC_REL32"; case 27: return "R_PPC_PLT32"; case 28: return "R_PPC_PLTREL32"; case 29: return "R_PPC_PLT16_LO"; case 30: return "R_PPC_PLT16_HI"; case 31: return "R_PPC_PLT16_HA"; case 32: return "R_PPC_SDAREL16"; case 33: return "R_PPC_SECTOFF"; case 34: return "R_PPC_SECTOFF_LO"; case 35: return "R_PPC_SECTOFF_HI"; case 36: return "R_PPC_SECTOFF_HA"; case 67: return "R_PPC_TLS"; case 68: return "R_PPC_DTPMOD32"; case 69: return "R_PPC_TPREL16"; case 70: return "R_PPC_TPREL16_LO"; case 71: return "R_PPC_TPREL16_HI"; case 72: return "R_PPC_TPREL16_HA"; case 73: return "R_PPC_TPREL32"; case 74: return "R_PPC_DTPREL16"; case 75: return "R_PPC_DTPREL16_LO"; case 76: return "R_PPC_DTPREL16_HI"; case 77: return "R_PPC_DTPREL16_HA"; case 78: return "R_PPC_DTPREL32"; case 79: return "R_PPC_GOT_TLSGD16"; case 80: return "R_PPC_GOT_TLSGD16_LO"; case 81: return "R_PPC_GOT_TLSGD16_HI"; case 82: return "R_PPC_GOT_TLSGD16_HA"; case 83: return "R_PPC_GOT_TLSLD16"; case 84: return "R_PPC_GOT_TLSLD16_LO"; case 85: return "R_PPC_GOT_TLSLD16_HI"; case 86: return "R_PPC_GOT_TLSLD16_HA"; case 87: return "R_PPC_GOT_TPREL16"; case 88: return "R_PPC_GOT_TPREL16_LO"; case 89: return "R_PPC_GOT_TPREL16_HI"; case 90: return "R_PPC_GOT_TPREL16_HA"; case 101: return "R_PPC_EMB_NADDR32"; case 102: return "R_PPC_EMB_NADDR16"; case 103: return "R_PPC_EMB_NADDR16_LO"; case 104: return "R_PPC_EMB_NADDR16_HI"; case 105: return "R_PPC_EMB_NADDR16_HA"; case 106: return "R_PPC_EMB_SDAI16"; case 107: return "R_PPC_EMB_SDA2I16"; case 108: return "R_PPC_EMB_SDA2REL"; case 109: return "R_PPC_EMB_SDA21"; case 110: return "R_PPC_EMB_MRKREF"; case 111: return "R_PPC_EMB_RELSEC16"; case 112: return "R_PPC_EMB_RELST_LO"; case 113: return "R_PPC_EMB_RELST_HI"; case 114: return "R_PPC_EMB_RELST_HA"; case 115: return "R_PPC_EMB_BIT_FLD"; case 116: return "R_PPC_EMB_RELSDA"; default: return ""; } case EM_SPARC: case EM_SPARCV9: switch(type) { case 0: return "R_SPARC_NONE"; case 1: return "R_SPARC_8"; case 2: return "R_SPARC_16"; case 3: return "R_SPARC_32"; case 4: return "R_SPARC_DISP8"; case 5: return "R_SPARC_DISP16"; case 6: return "R_SPARC_DISP32"; case 7: return "R_SPARC_WDISP30"; case 8: return "R_SPARC_WDISP22"; case 9: return "R_SPARC_HI22"; case 10: return "R_SPARC_22"; case 11: return "R_SPARC_13"; case 12: return "R_SPARC_LO10"; case 13: return "R_SPARC_GOT10"; case 14: return "R_SPARC_GOT13"; case 15: return "R_SPARC_GOT22"; case 16: return "R_SPARC_PC10"; case 17: return "R_SPARC_PC22"; case 18: return "R_SPARC_WPLT30"; case 19: return "R_SPARC_COPY"; case 20: return "R_SPARC_GLOB_DAT"; case 21: return "R_SPARC_JMP_SLOT"; case 22: return "R_SPARC_RELATIVE"; case 23: return "R_SPARC_UA32"; case 24: return "R_SPARC_PLT32"; case 25: return "R_SPARC_HIPLT22"; case 26: return "R_SPARC_LOPLT10"; case 27: return "R_SPARC_PCPLT32"; case 28: return "R_SPARC_PCPLT22"; case 29: return "R_SPARC_PCPLT10"; case 30: return "R_SPARC_10"; case 31: return "R_SPARC_11"; case 32: return "R_SPARC_64"; case 33: return "R_SPARC_OLO10"; case 34: return "R_SPARC_HH22"; case 35: return "R_SPARC_HM10"; case 36: return "R_SPARC_LM22"; case 37: return "R_SPARC_PC_HH22"; case 38: return "R_SPARC_PC_HM10"; case 39: return "R_SPARC_PC_LM22"; case 40: return "R_SPARC_WDISP16"; case 41: return "R_SPARC_WDISP19"; case 42: return "R_SPARC_GLOB_JMP"; case 43: return "R_SPARC_7"; case 44: return "R_SPARC_5"; case 45: return "R_SPARC_6"; case 46: return "R_SPARC_DISP64"; case 47: return "R_SPARC_PLT64"; case 48: return "R_SPARC_HIX22"; case 49: return "R_SPARC_LOX10"; case 50: return "R_SPARC_H44"; case 51: return "R_SPARC_M44"; case 52: return "R_SPARC_L44"; case 53: return "R_SPARC_REGISTER"; case 54: return "R_SPARC_UA64"; case 55: return "R_SPARC_UA16"; case 56: return "R_SPARC_TLS_GD_HI22"; case 57: return "R_SPARC_TLS_GD_LO10"; case 58: return "R_SPARC_TLS_GD_ADD"; case 59: return "R_SPARC_TLS_GD_CALL"; case 60: return "R_SPARC_TLS_LDM_HI22"; case 61: return "R_SPARC_TLS_LDM_LO10"; case 62: return "R_SPARC_TLS_LDM_ADD"; case 63: return "R_SPARC_TLS_LDM_CALL"; case 64: return "R_SPARC_TLS_LDO_HIX22"; case 65: return "R_SPARC_TLS_LDO_LOX10"; case 66: return "R_SPARC_TLS_LDO_ADD"; case 67: return "R_SPARC_TLS_IE_HI22"; case 68: return "R_SPARC_TLS_IE_LO10"; case 69: return "R_SPARC_TLS_IE_LD"; case 70: return "R_SPARC_TLS_IE_LDX"; case 71: return "R_SPARC_TLS_IE_ADD"; case 72: return "R_SPARC_TLS_LE_HIX22"; case 73: return "R_SPARC_TLS_LE_LOX10"; case 74: return "R_SPARC_TLS_DTPMOD32"; case 75: return "R_SPARC_TLS_DTPMOD64"; case 76: return "R_SPARC_TLS_DTPOFF32"; case 77: return "R_SPARC_TLS_DTPOFF64"; case 78: return "R_SPARC_TLS_TPOFF32"; case 79: return "R_SPARC_TLS_TPOFF64"; default: return ""; } case EM_X86_64: switch(type) { case 0: return "R_X86_64_NONE"; case 1: return "R_X86_64_64"; case 2: return "R_X86_64_PC32"; case 3: return "R_X86_64_GOT32"; case 4: return "R_X86_64_PLT32"; case 5: return "R_X86_64_COPY"; case 6: return "R_X86_64_GLOB_DAT"; case 7: return "R_X86_64_JMP_SLOT"; case 8: return "R_X86_64_RELATIVE"; case 9: return "R_X86_64_GOTPCREL"; case 10: return "R_X86_64_32"; case 11: return "R_X86_64_32S"; case 12: return "R_X86_64_16"; case 13: return "R_X86_64_PC16"; case 14: return "R_X86_64_8"; case 15: return "R_X86_64_PC8"; case 16: return "R_X86_64_DTPMOD64"; case 17: return "R_X86_64_DTPOFF64"; case 18: return "R_X86_64_TPOFF64"; case 19: return "R_X86_64_TLSGD"; case 20: return "R_X86_64_TLSLD"; case 21: return "R_X86_64_DTPOFF32"; case 22: return "R_X86_64_GOTTPOFF"; case 23: return "R_X86_64_TPOFF32"; case 24: return "R_X86_64_PC64"; case 25: return "R_X86_64_GOTOFF64"; case 26: return "R_X86_64_GOTPC32"; case 27: return "R_X86_64_GOT64"; case 28: return "R_X86_64_GOTPCREL64"; case 29: return "R_X86_64_GOTPC64"; case 30: return "R_X86_64_GOTPLT64"; case 31: return "R_X86_64_PLTOFF64"; case 32: return "R_X86_64_SIZE32"; case 33: return "R_X86_64_SIZE64"; case 34: return "R_X86_64_GOTPC32_TLSDESC"; case 35: return "R_X86_64_TLSDESC_CALL"; case 36: return "R_X86_64_TLSDESC"; case 37: return "R_X86_64_IRELATIVE"; default: return ""; } default: return ""; } } static const char * note_type(const char *name, unsigned int et, unsigned int nt) { if ((strcmp(name, "CORE") == 0 || strcmp(name, "LINUX") == 0) && et == ET_CORE) return note_type_linux_core(nt); else if (strcmp(name, "FreeBSD") == 0) if (et == ET_CORE) return note_type_freebsd_core(nt); else return note_type_freebsd(nt); else if (strcmp(name, "GNU") == 0 && et != ET_CORE) return note_type_gnu(nt); else if (strcmp(name, "NetBSD") == 0 && et != ET_CORE) return note_type_netbsd(nt); else if (strcmp(name, "OpenBSD") == 0 && et != ET_CORE) return note_type_openbsd(nt); return note_type_unknown(nt); } static const char * note_type_freebsd(unsigned int nt) { switch (nt) { case 1: return "NT_FREEBSD_ABI_TAG"; case 2: return "NT_FREEBSD_NOINIT_TAG"; case 3: return "NT_FREEBSD_ARCH_TAG"; default: return (note_type_unknown(nt)); } } static const char * note_type_freebsd_core(unsigned int nt) { switch (nt) { case 1: return "NT_PRSTATUS"; case 2: return "NT_FPREGSET"; case 3: return "NT_PRPSINFO"; case 7: return "NT_THRMISC"; case 8: return "NT_PROCSTAT_PROC"; case 9: return "NT_PROCSTAT_FILES"; case 10: return "NT_PROCSTAT_VMMAP"; case 11: return "NT_PROCSTAT_GROUPS"; case 12: return "NT_PROCSTAT_UMASK"; case 13: return "NT_PROCSTAT_RLIMIT"; case 14: return "NT_PROCSTAT_OSREL"; case 15: return "NT_PROCSTAT_PSSTRINGS"; case 16: return "NT_PROCSTAT_AUXV"; case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)"; default: return (note_type_unknown(nt)); } } static const char * note_type_linux_core(unsigned int nt) { switch (nt) { case 1: return "NT_PRSTATUS (Process status)"; case 2: return "NT_FPREGSET (Floating point information)"; case 3: return "NT_PRPSINFO (Process information)"; case 4: return "NT_TASKSTRUCT (Task structure)"; case 6: return "NT_AUXV (Auxiliary vector)"; case 10: return "NT_PSTATUS (Linux process status)"; case 12: return "NT_FPREGS (Linux floating point regset)"; case 13: return "NT_PSINFO (Linux process information)"; case 16: return "NT_LWPSTATUS (Linux lwpstatus_t type)"; case 17: return "NT_LWPSINFO (Linux lwpinfo_t type)"; case 18: return "NT_WIN32PSTATUS (win32_pstatus structure)"; case 0x100: return "NT_PPC_VMX (ppc Altivec registers)"; case 0x102: return "NT_PPC_VSX (ppc VSX registers)"; case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)"; case 0x300: return "NT_S390_HIGH_GPRS (s390 upper register halves)"; case 0x301: return "NT_S390_TIMER (s390 timer register)"; case 0x302: return "NT_S390_TODCMP (s390 TOD comparator register)"; case 0x303: return "NT_S390_TODPREG (s390 TOD programmable register)"; case 0x304: return "NT_S390_CTRS (s390 control registers)"; case 0x305: return "NT_S390_PREFIX (s390 prefix register)"; case 0x400: return "NT_ARM_VFP (arm VFP registers)"; case 0x46494c45UL: return "NT_FILE (mapped files)"; case 0x46E62B7FUL: return "NT_PRXFPREG (Linux user_xfpregs structure)"; case 0x53494749UL: return "NT_SIGINFO (siginfo_t data)"; default: return (note_type_unknown(nt)); } } static const char * note_type_gnu(unsigned int nt) { switch (nt) { case 1: return "NT_GNU_ABI_TAG"; case 2: return "NT_GNU_HWCAP (Hardware capabilities)"; case 3: return "NT_GNU_BUILD_ID (Build id set by ld(1))"; case 4: return "NT_GNU_GOLD_VERSION (GNU gold version)"; default: return (note_type_unknown(nt)); } } static const char * note_type_netbsd(unsigned int nt) { switch (nt) { case 1: return "NT_NETBSD_IDENT"; default: return (note_type_unknown(nt)); } } static const char * note_type_openbsd(unsigned int nt) { switch (nt) { case 1: return "NT_OPENBSD_IDENT"; default: return (note_type_unknown(nt)); } } static const char * note_type_unknown(unsigned int nt) { static char s_nt[32]; snprintf(s_nt, sizeof(s_nt), nt >= 0x100 ? "" : "", nt); return (s_nt); } static struct { const char *name; int value; } l_flag[] = { {"EXACT_MATCH", LL_EXACT_MATCH}, {"IGNORE_INT_VER", LL_IGNORE_INT_VER}, {"REQUIRE_MINOR", LL_REQUIRE_MINOR}, {"EXPORTS", LL_EXPORTS}, {"DELAY_LOAD", LL_DELAY_LOAD}, {"DELTA", LL_DELTA}, {NULL, 0} }; static struct mips_option mips_exceptions_option[] = { {OEX_PAGE0, "PAGE0"}, {OEX_SMM, "SMM"}, {OEX_PRECISEFP, "PRECISEFP"}, {OEX_DISMISS, "DISMISS"}, {0, NULL} }; static struct mips_option mips_pad_option[] = { {OPAD_PREFIX, "PREFIX"}, {OPAD_POSTFIX, "POSTFIX"}, {OPAD_SYMBOL, "SYMBOL"}, {0, NULL} }; static struct mips_option mips_hwpatch_option[] = { {OHW_R4KEOP, "R4KEOP"}, {OHW_R8KPFETCH, "R8KPFETCH"}, {OHW_R5KEOP, "R5KEOP"}, {OHW_R5KCVTL, "R5KCVTL"}, {0, NULL} }; static struct mips_option mips_hwa_option[] = { {OHWA0_R4KEOP_CHECKED, "R4KEOP_CHECKED"}, {OHWA0_R4KEOP_CLEAN, "R4KEOP_CLEAN"}, {0, NULL} }; static struct mips_option mips_hwo_option[] = { {OHWO0_FIXADE, "FIXADE"}, {0, NULL} }; static const char * option_kind(uint8_t kind) { static char s_kind[32]; switch (kind) { case ODK_NULL: return "NULL"; case ODK_REGINFO: return "REGINFO"; case ODK_EXCEPTIONS: return "EXCEPTIONS"; case ODK_PAD: return "PAD"; case ODK_HWPATCH: return "HWPATCH"; case ODK_FILL: return "FILL"; case ODK_TAGS: return "TAGS"; case ODK_HWAND: return "HWAND"; case ODK_HWOR: return "HWOR"; case ODK_GP_GROUP: return "GP_GROUP"; case ODK_IDENT: return "IDENT"; default: snprintf(s_kind, sizeof(s_kind), "", kind); return (s_kind); } } static const char * top_tag(unsigned int tag) { static char s_top_tag[32]; switch (tag) { case 1: return "File Attributes"; case 2: return "Section Attributes"; case 3: return "Symbol Attributes"; default: snprintf(s_top_tag, sizeof(s_top_tag), "Unknown tag: %u", tag); return (s_top_tag); } } static const char * aeabi_cpu_arch(uint64_t arch) { static char s_cpu_arch[32]; switch (arch) { case 0: return "Pre-V4"; case 1: return "ARM v4"; case 2: return "ARM v4T"; case 3: return "ARM v5T"; case 4: return "ARM v5TE"; case 5: return "ARM v5TEJ"; case 6: return "ARM v6"; case 7: return "ARM v6KZ"; case 8: return "ARM v6T2"; case 9: return "ARM v6K"; case 10: return "ARM v7"; case 11: return "ARM v6-M"; case 12: return "ARM v6S-M"; case 13: return "ARM v7E-M"; default: snprintf(s_cpu_arch, sizeof(s_cpu_arch), "Unknown (%ju)", (uintmax_t) arch); return (s_cpu_arch); } } static const char * aeabi_cpu_arch_profile(uint64_t pf) { static char s_arch_profile[32]; switch (pf) { case 0: return "Not applicable"; case 0x41: /* 'A' */ return "Application Profile"; case 0x52: /* 'R' */ return "Real-Time Profile"; case 0x4D: /* 'M' */ return "Microcontroller Profile"; case 0x53: /* 'S' */ return "Application or Real-Time Profile"; default: snprintf(s_arch_profile, sizeof(s_arch_profile), "Unknown (%ju)\n", (uintmax_t) pf); return (s_arch_profile); } } static const char * aeabi_arm_isa(uint64_t ai) { static char s_ai[32]; switch (ai) { case 0: return "No"; case 1: return "Yes"; default: snprintf(s_ai, sizeof(s_ai), "Unknown (%ju)\n", (uintmax_t) ai); return (s_ai); } } static const char * aeabi_thumb_isa(uint64_t ti) { static char s_ti[32]; switch (ti) { case 0: return "No"; case 1: return "16-bit Thumb"; case 2: return "32-bit Thumb"; default: snprintf(s_ti, sizeof(s_ti), "Unknown (%ju)\n", (uintmax_t) ti); return (s_ti); } } static const char * aeabi_fp_arch(uint64_t fp) { static char s_fp_arch[32]; switch (fp) { case 0: return "No"; case 1: return "VFPv1"; case 2: return "VFPv2"; case 3: return "VFPv3"; case 4: return "VFPv3-D16"; case 5: return "VFPv4"; case 6: return "VFPv4-D16"; default: snprintf(s_fp_arch, sizeof(s_fp_arch), "Unknown (%ju)", (uintmax_t) fp); return (s_fp_arch); } } static const char * aeabi_wmmx_arch(uint64_t wmmx) { static char s_wmmx[32]; switch (wmmx) { case 0: return "No"; case 1: return "WMMXv1"; case 2: return "WMMXv2"; default: snprintf(s_wmmx, sizeof(s_wmmx), "Unknown (%ju)", (uintmax_t) wmmx); return (s_wmmx); } } static const char * aeabi_adv_simd_arch(uint64_t simd) { static char s_simd[32]; switch (simd) { case 0: return "No"; case 1: return "NEONv1"; case 2: return "NEONv2"; default: snprintf(s_simd, sizeof(s_simd), "Unknown (%ju)", (uintmax_t) simd); return (s_simd); } } static const char * aeabi_pcs_config(uint64_t pcs) { static char s_pcs[32]; switch (pcs) { case 0: return "None"; case 1: return "Bare platform"; case 2: return "Linux"; case 3: return "Linux DSO"; case 4: return "Palm OS 2004"; case 5: return "Palm OS (future)"; case 6: return "Symbian OS 2004"; case 7: return "Symbian OS (future)"; default: snprintf(s_pcs, sizeof(s_pcs), "Unknown (%ju)", (uintmax_t) pcs); return (s_pcs); } } static const char * aeabi_pcs_r9(uint64_t r9) { static char s_r9[32]; switch (r9) { case 0: return "V6"; case 1: return "SB"; case 2: return "TLS pointer"; case 3: return "Unused"; default: snprintf(s_r9, sizeof(s_r9), "Unknown (%ju)", (uintmax_t) r9); return (s_r9); } } static const char * aeabi_pcs_rw(uint64_t rw) { static char s_rw[32]; switch (rw) { case 0: return "Absolute"; case 1: return "PC-relative"; case 2: return "SB-relative"; case 3: return "None"; default: snprintf(s_rw, sizeof(s_rw), "Unknown (%ju)", (uintmax_t) rw); return (s_rw); } } static const char * aeabi_pcs_ro(uint64_t ro) { static char s_ro[32]; switch (ro) { case 0: return "Absolute"; case 1: return "PC-relative"; case 2: return "None"; default: snprintf(s_ro, sizeof(s_ro), "Unknown (%ju)", (uintmax_t) ro); return (s_ro); } } static const char * aeabi_pcs_got(uint64_t got) { static char s_got[32]; switch (got) { case 0: return "None"; case 1: return "direct"; case 2: return "indirect via GOT"; default: snprintf(s_got, sizeof(s_got), "Unknown (%ju)", (uintmax_t) got); return (s_got); } } static const char * aeabi_pcs_wchar_t(uint64_t wt) { static char s_wt[32]; switch (wt) { case 0: return "None"; case 2: return "wchar_t size 2"; case 4: return "wchar_t size 4"; default: snprintf(s_wt, sizeof(s_wt), "Unknown (%ju)", (uintmax_t) wt); return (s_wt); } } static const char * aeabi_enum_size(uint64_t es) { static char s_es[32]; switch (es) { case 0: return "None"; case 1: return "smallest"; case 2: return "32-bit"; case 3: return "visible 32-bit"; default: snprintf(s_es, sizeof(s_es), "Unknown (%ju)", (uintmax_t) es); return (s_es); } } static const char * aeabi_align_needed(uint64_t an) { static char s_align_n[64]; switch (an) { case 0: return "No"; case 1: return "8-byte align"; case 2: return "4-byte align"; case 3: return "Reserved"; default: if (an >= 4 && an <= 12) snprintf(s_align_n, sizeof(s_align_n), "8-byte align" " and up to 2^%ju-byte extended align", (uintmax_t) an); else snprintf(s_align_n, sizeof(s_align_n), "Unknown (%ju)", (uintmax_t) an); return (s_align_n); } } static const char * aeabi_align_preserved(uint64_t ap) { static char s_align_p[128]; switch (ap) { case 0: return "No"; case 1: return "8-byte align"; case 2: return "8-byte align and SP % 8 == 0"; case 3: return "Reserved"; default: if (ap >= 4 && ap <= 12) snprintf(s_align_p, sizeof(s_align_p), "8-byte align" " and SP %% 8 == 0 and up to 2^%ju-byte extended" " align", (uintmax_t) ap); else snprintf(s_align_p, sizeof(s_align_p), "Unknown (%ju)", (uintmax_t) ap); return (s_align_p); } } static const char * aeabi_fp_rounding(uint64_t fr) { static char s_fp_r[32]; switch (fr) { case 0: return "Unused"; case 1: return "Needed"; default: snprintf(s_fp_r, sizeof(s_fp_r), "Unknown (%ju)", (uintmax_t) fr); return (s_fp_r); } } static const char * aeabi_fp_denormal(uint64_t fd) { static char s_fp_d[32]; switch (fd) { case 0: return "Unused"; case 1: return "Needed"; case 2: return "Sign Only"; default: snprintf(s_fp_d, sizeof(s_fp_d), "Unknown (%ju)", (uintmax_t) fd); return (s_fp_d); } } static const char * aeabi_fp_exceptions(uint64_t fe) { static char s_fp_e[32]; switch (fe) { case 0: return "Unused"; case 1: return "Needed"; default: snprintf(s_fp_e, sizeof(s_fp_e), "Unknown (%ju)", (uintmax_t) fe); return (s_fp_e); } } static const char * aeabi_fp_user_exceptions(uint64_t fu) { static char s_fp_u[32]; switch (fu) { case 0: return "Unused"; case 1: return "Needed"; default: snprintf(s_fp_u, sizeof(s_fp_u), "Unknown (%ju)", (uintmax_t) fu); return (s_fp_u); } } static const char * aeabi_fp_number_model(uint64_t fn) { static char s_fp_n[32]; switch (fn) { case 0: return "Unused"; case 1: return "IEEE 754 normal"; case 2: return "RTABI"; case 3: return "IEEE 754"; default: snprintf(s_fp_n, sizeof(s_fp_n), "Unknown (%ju)", (uintmax_t) fn); return (s_fp_n); } } static const char * aeabi_fp_16bit_format(uint64_t fp16) { static char s_fp_16[64]; switch (fp16) { case 0: return "None"; case 1: return "IEEE 754"; case 2: return "VFPv3/Advanced SIMD (alternative format)"; default: snprintf(s_fp_16, sizeof(s_fp_16), "Unknown (%ju)", (uintmax_t) fp16); return (s_fp_16); } } static const char * aeabi_mpext(uint64_t mp) { static char s_mp[32]; switch (mp) { case 0: return "Not allowed"; case 1: return "Allowed"; default: snprintf(s_mp, sizeof(s_mp), "Unknown (%ju)", (uintmax_t) mp); return (s_mp); } } static const char * aeabi_div(uint64_t du) { static char s_du[32]; switch (du) { case 0: return "Yes (V7-R/V7-M)"; case 1: return "No"; case 2: return "Yes (V7-A)"; default: snprintf(s_du, sizeof(s_du), "Unknown (%ju)", (uintmax_t) du); return (s_du); } } static const char * aeabi_t2ee(uint64_t t2ee) { static char s_t2ee[32]; switch (t2ee) { case 0: return "Not allowed"; case 1: return "Allowed"; default: snprintf(s_t2ee, sizeof(s_t2ee), "Unknown(%ju)", (uintmax_t) t2ee); return (s_t2ee); } } static const char * aeabi_hardfp(uint64_t hfp) { static char s_hfp[32]; switch (hfp) { case 0: return "Tag_FP_arch"; case 1: return "only SP"; case 2: return "only DP"; case 3: return "both SP and DP"; default: snprintf(s_hfp, sizeof(s_hfp), "Unknown (%ju)", (uintmax_t) hfp); return (s_hfp); } } static const char * aeabi_vfp_args(uint64_t va) { static char s_va[32]; switch (va) { case 0: return "AAPCS (base variant)"; case 1: return "AAPCS (VFP variant)"; case 2: return "toolchain-specific"; default: snprintf(s_va, sizeof(s_va), "Unknown (%ju)", (uintmax_t) va); return (s_va); } } static const char * aeabi_wmmx_args(uint64_t wa) { static char s_wa[32]; switch (wa) { case 0: return "AAPCS (base variant)"; case 1: return "Intel WMMX"; case 2: return "toolchain-specific"; default: snprintf(s_wa, sizeof(s_wa), "Unknown(%ju)", (uintmax_t) wa); return (s_wa); } } static const char * aeabi_unaligned_access(uint64_t ua) { static char s_ua[32]; switch (ua) { case 0: return "Not allowed"; case 1: return "Allowed"; default: snprintf(s_ua, sizeof(s_ua), "Unknown(%ju)", (uintmax_t) ua); return (s_ua); } } static const char * aeabi_fp_hpext(uint64_t fh) { static char s_fh[32]; switch (fh) { case 0: return "Not allowed"; case 1: return "Allowed"; default: snprintf(s_fh, sizeof(s_fh), "Unknown(%ju)", (uintmax_t) fh); return (s_fh); } } static const char * aeabi_optm_goal(uint64_t og) { static char s_og[32]; switch (og) { case 0: return "None"; case 1: return "Speed"; case 2: return "Speed aggressive"; case 3: return "Space"; case 4: return "Space aggressive"; case 5: return "Debugging"; case 6: return "Best Debugging"; default: snprintf(s_og, sizeof(s_og), "Unknown(%ju)", (uintmax_t) og); return (s_og); } } static const char * aeabi_fp_optm_goal(uint64_t fog) { static char s_fog[32]; switch (fog) { case 0: return "None"; case 1: return "Speed"; case 2: return "Speed aggressive"; case 3: return "Space"; case 4: return "Space aggressive"; case 5: return "Accurary"; case 6: return "Best Accurary"; default: snprintf(s_fog, sizeof(s_fog), "Unknown(%ju)", (uintmax_t) fog); return (s_fog); } } static const char * aeabi_virtual(uint64_t vt) { static char s_virtual[64]; switch (vt) { case 0: return "No"; case 1: return "TrustZone"; case 2: return "Virtualization extension"; case 3: return "TrustZone and virtualization extension"; default: snprintf(s_virtual, sizeof(s_virtual), "Unknown(%ju)", (uintmax_t) vt); return (s_virtual); } } static struct { uint64_t tag; const char *s_tag; const char *(*get_desc)(uint64_t val); } aeabi_tags[] = { {4, "Tag_CPU_raw_name", NULL}, {5, "Tag_CPU_name", NULL}, {6, "Tag_CPU_arch", aeabi_cpu_arch}, {7, "Tag_CPU_arch_profile", aeabi_cpu_arch_profile}, {8, "Tag_ARM_ISA_use", aeabi_arm_isa}, {9, "Tag_THUMB_ISA_use", aeabi_thumb_isa}, {10, "Tag_FP_arch", aeabi_fp_arch}, {11, "Tag_WMMX_arch", aeabi_wmmx_arch}, {12, "Tag_Advanced_SIMD_arch", aeabi_adv_simd_arch}, {13, "Tag_PCS_config", aeabi_pcs_config}, {14, "Tag_ABI_PCS_R9_use", aeabi_pcs_r9}, {15, "Tag_ABI_PCS_RW_data", aeabi_pcs_rw}, {16, "Tag_ABI_PCS_RO_data", aeabi_pcs_ro}, {17, "Tag_ABI_PCS_GOT_use", aeabi_pcs_got}, {18, "Tag_ABI_PCS_wchar_t", aeabi_pcs_wchar_t}, {19, "Tag_ABI_FP_rounding", aeabi_fp_rounding}, {20, "Tag_ABI_FP_denormal", aeabi_fp_denormal}, {21, "Tag_ABI_FP_exceptions", aeabi_fp_exceptions}, {22, "Tag_ABI_FP_user_exceptions", aeabi_fp_user_exceptions}, {23, "Tag_ABI_FP_number_model", aeabi_fp_number_model}, {24, "Tag_ABI_align_needed", aeabi_align_needed}, {25, "Tag_ABI_align_preserved", aeabi_align_preserved}, {26, "Tag_ABI_enum_size", aeabi_enum_size}, {27, "Tag_ABI_HardFP_use", aeabi_hardfp}, {28, "Tag_ABI_VFP_args", aeabi_vfp_args}, {29, "Tag_ABI_WMMX_args", aeabi_wmmx_args}, {30, "Tag_ABI_optimization_goals", aeabi_optm_goal}, {31, "Tag_ABI_FP_optimization_goals", aeabi_fp_optm_goal}, {32, "Tag_compatibility", NULL}, {34, "Tag_CPU_unaligned_access", aeabi_unaligned_access}, {36, "Tag_FP_HP_extension", aeabi_fp_hpext}, {38, "Tag_ABI_FP_16bit_format", aeabi_fp_16bit_format}, {42, "Tag_MPextension_use", aeabi_mpext}, {44, "Tag_DIV_use", aeabi_div}, {64, "Tag_nodefaults", NULL}, {65, "Tag_also_compatible_with", NULL}, {66, "Tag_T2EE_use", aeabi_t2ee}, {67, "Tag_conformance", NULL}, {68, "Tag_Virtualization_use", aeabi_virtual}, {70, "Tag_MPextension_use", aeabi_mpext}, }; static const char * mips_abi_fp(uint64_t fp) { static char s_mips_abi_fp[64]; switch (fp) { case 0: return "N/A"; case 1: return "Hard float (double precision)"; case 2: return "Hard float (single precision)"; case 3: return "Soft float"; case 4: return "64-bit float (-mips32r2 -mfp64)"; default: snprintf(s_mips_abi_fp, sizeof(s_mips_abi_fp), "Unknown(%ju)", (uintmax_t) fp); return (s_mips_abi_fp); } } static const char * ppc_abi_fp(uint64_t fp) { static char s_ppc_abi_fp[64]; switch (fp) { case 0: return "N/A"; case 1: return "Hard float (double precision)"; case 2: return "Soft float"; case 3: return "Hard float (single precision)"; default: snprintf(s_ppc_abi_fp, sizeof(s_ppc_abi_fp), "Unknown(%ju)", (uintmax_t) fp); return (s_ppc_abi_fp); } } static const char * ppc_abi_vector(uint64_t vec) { static char s_vec[64]; switch (vec) { case 0: return "N/A"; case 1: return "Generic purpose registers"; case 2: return "AltiVec registers"; case 3: return "SPE registers"; default: snprintf(s_vec, sizeof(s_vec), "Unknown(%ju)", (uintmax_t) vec); return (s_vec); } } static const char * dwarf_reg(unsigned int mach, unsigned int reg) { switch (mach) { case EM_386: switch (reg) { case 0: return "eax"; case 1: return "ecx"; case 2: return "edx"; case 3: return "ebx"; case 4: return "esp"; case 5: return "ebp"; case 6: return "esi"; case 7: return "edi"; case 8: return "eip"; case 9: return "eflags"; case 11: return "st0"; case 12: return "st1"; case 13: return "st2"; case 14: return "st3"; case 15: return "st4"; case 16: return "st5"; case 17: return "st6"; case 18: return "st7"; case 21: return "xmm0"; case 22: return "xmm1"; case 23: return "xmm2"; case 24: return "xmm3"; case 25: return "xmm4"; case 26: return "xmm5"; case 27: return "xmm6"; case 28: return "xmm7"; case 29: return "mm0"; case 30: return "mm1"; case 31: return "mm2"; case 32: return "mm3"; case 33: return "mm4"; case 34: return "mm5"; case 35: return "mm6"; case 36: return "mm7"; case 37: return "fcw"; case 38: return "fsw"; case 39: return "mxcsr"; case 40: return "es"; case 41: return "cs"; case 42: return "ss"; case 43: return "ds"; case 44: return "fs"; case 45: return "gs"; case 48: return "tr"; case 49: return "ldtr"; default: return (NULL); } case EM_X86_64: switch (reg) { case 0: return "rax"; case 1: return "rdx"; case 2: return "rcx"; case 3: return "rbx"; case 4: return "rsi"; case 5: return "rdi"; case 6: return "rbp"; case 7: return "rsp"; case 16: return "rip"; case 17: return "xmm0"; case 18: return "xmm1"; case 19: return "xmm2"; case 20: return "xmm3"; case 21: return "xmm4"; case 22: return "xmm5"; case 23: return "xmm6"; case 24: return "xmm7"; case 25: return "xmm8"; case 26: return "xmm9"; case 27: return "xmm10"; case 28: return "xmm11"; case 29: return "xmm12"; case 30: return "xmm13"; case 31: return "xmm14"; case 32: return "xmm15"; case 33: return "st0"; case 34: return "st1"; case 35: return "st2"; case 36: return "st3"; case 37: return "st4"; case 38: return "st5"; case 39: return "st6"; case 40: return "st7"; case 41: return "mm0"; case 42: return "mm1"; case 43: return "mm2"; case 44: return "mm3"; case 45: return "mm4"; case 46: return "mm5"; case 47: return "mm6"; case 48: return "mm7"; case 49: return "rflags"; case 50: return "es"; case 51: return "cs"; case 52: return "ss"; case 53: return "ds"; case 54: return "fs"; case 55: return "gs"; case 58: return "fs.base"; case 59: return "gs.base"; case 62: return "tr"; case 63: return "ldtr"; case 64: return "mxcsr"; case 65: return "fcw"; case 66: return "fsw"; default: return (NULL); } default: return (NULL); } } static void dump_ehdr(struct readelf *re) { size_t shnum, shstrndx; int i; printf("ELF Header:\n"); /* e_ident[]. */ printf(" Magic: "); for (i = 0; i < EI_NIDENT; i++) printf("%.2x ", re->ehdr.e_ident[i]); putchar('\n'); /* EI_CLASS. */ printf("%-37s%s\n", " Class:", elf_class(re->ehdr.e_ident[EI_CLASS])); /* EI_DATA. */ printf("%-37s%s\n", " Data:", elf_endian(re->ehdr.e_ident[EI_DATA])); /* EI_VERSION. */ printf("%-37s%d %s\n", " Version:", re->ehdr.e_ident[EI_VERSION], elf_ver(re->ehdr.e_ident[EI_VERSION])); /* EI_OSABI. */ printf("%-37s%s\n", " OS/ABI:", elf_osabi(re->ehdr.e_ident[EI_OSABI])); /* EI_ABIVERSION. */ printf("%-37s%d\n", " ABI Version:", re->ehdr.e_ident[EI_ABIVERSION]); /* e_type. */ printf("%-37s%s\n", " Type:", elf_type(re->ehdr.e_type)); /* e_machine. */ printf("%-37s%s\n", " Machine:", elf_machine(re->ehdr.e_machine)); /* e_version. */ printf("%-37s%#x\n", " Version:", re->ehdr.e_version); /* e_entry. */ printf("%-37s%#jx\n", " Entry point address:", (uintmax_t)re->ehdr.e_entry); /* e_phoff. */ printf("%-37s%ju (bytes into file)\n", " Start of program headers:", (uintmax_t)re->ehdr.e_phoff); /* e_shoff. */ printf("%-37s%ju (bytes into file)\n", " Start of section headers:", (uintmax_t)re->ehdr.e_shoff); /* e_flags. */ printf("%-37s%#x", " Flags:", re->ehdr.e_flags); dump_eflags(re, re->ehdr.e_flags); putchar('\n'); /* e_ehsize. */ printf("%-37s%u (bytes)\n", " Size of this header:", re->ehdr.e_ehsize); /* e_phentsize. */ printf("%-37s%u (bytes)\n", " Size of program headers:", re->ehdr.e_phentsize); /* e_phnum. */ printf("%-37s%u\n", " Number of program headers:", re->ehdr.e_phnum); /* e_shentsize. */ printf("%-37s%u (bytes)\n", " Size of section headers:", re->ehdr.e_shentsize); /* e_shnum. */ printf("%-37s%u", " Number of section headers:", re->ehdr.e_shnum); if (re->ehdr.e_shnum == SHN_UNDEF) { /* Extended section numbering is in use. */ if (elf_getshnum(re->elf, &shnum)) printf(" (%ju)", (uintmax_t)shnum); } putchar('\n'); /* e_shstrndx. */ printf("%-37s%u", " Section header string table index:", re->ehdr.e_shstrndx); if (re->ehdr.e_shstrndx == SHN_XINDEX) { /* Extended section numbering is in use. */ if (elf_getshstrndx(re->elf, &shstrndx)) printf(" (%ju)", (uintmax_t)shstrndx); } putchar('\n'); } static void dump_eflags(struct readelf *re, uint64_t e_flags) { struct eflags_desc *edesc; int arm_eabi; edesc = NULL; switch (re->ehdr.e_machine) { case EM_ARM: arm_eabi = (e_flags & EF_ARM_EABIMASK) >> 24; if (arm_eabi == 0) printf(", GNU EABI"); else if (arm_eabi <= 5) printf(", Version%d EABI", arm_eabi); edesc = arm_eflags_desc; break; case EM_MIPS: case EM_MIPS_RS3_LE: switch ((e_flags & EF_MIPS_ARCH) >> 28) { case 0: printf(", mips1"); break; case 1: printf(", mips2"); break; case 2: printf(", mips3"); break; case 3: printf(", mips4"); break; case 4: printf(", mips5"); break; case 5: printf(", mips32"); break; case 6: printf(", mips64"); break; case 7: printf(", mips32r2"); break; case 8: printf(", mips64r2"); break; default: break; } switch ((e_flags & 0x00FF0000) >> 16) { case 0x81: printf(", 3900"); break; case 0x82: printf(", 4010"); break; case 0x83: printf(", 4100"); break; case 0x85: printf(", 4650"); break; case 0x87: printf(", 4120"); break; case 0x88: printf(", 4111"); break; case 0x8a: printf(", sb1"); break; case 0x8b: printf(", octeon"); break; case 0x8c: printf(", xlr"); break; case 0x91: printf(", 5400"); break; case 0x98: printf(", 5500"); break; case 0x99: printf(", 9000"); break; case 0xa0: printf(", loongson-2e"); break; case 0xa1: printf(", loongson-2f"); break; default: break; } switch ((e_flags & 0x0000F000) >> 12) { case 1: printf(", o32"); break; case 2: printf(", o64"); break; case 3: printf(", eabi32"); break; case 4: printf(", eabi64"); break; default: break; } edesc = mips_eflags_desc; break; case EM_PPC: case EM_PPC64: edesc = powerpc_eflags_desc; break; case EM_SPARC: case EM_SPARC32PLUS: case EM_SPARCV9: switch ((e_flags & EF_SPARCV9_MM)) { case EF_SPARCV9_TSO: printf(", tso"); break; case EF_SPARCV9_PSO: printf(", pso"); break; case EF_SPARCV9_MM: printf(", rmo"); break; default: break; } edesc = sparc_eflags_desc; break; default: break; } if (edesc != NULL) { while (edesc->desc != NULL) { if (e_flags & edesc->flag) printf(", %s", edesc->desc); edesc++; } } } static void dump_phdr(struct readelf *re) { const char *rawfile; GElf_Phdr phdr; size_t phnum; int i, j; #define PH_HDR "Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz", \ "MemSiz", "Flg", "Align" #define PH_CT phdr_type(phdr.p_type), (uintmax_t)phdr.p_offset, \ (uintmax_t)phdr.p_vaddr, (uintmax_t)phdr.p_paddr, \ (uintmax_t)phdr.p_filesz, (uintmax_t)phdr.p_memsz, \ phdr.p_flags & PF_R ? 'R' : ' ', \ phdr.p_flags & PF_W ? 'W' : ' ', \ phdr.p_flags & PF_X ? 'E' : ' ', \ (uintmax_t)phdr.p_align if (elf_getphnum(re->elf, &phnum) == 0) { warnx("elf_getphnum failed: %s", elf_errmsg(-1)); return; } if (phnum == 0) { printf("\nThere are no program headers in this file.\n"); return; } printf("\nElf file type is %s", elf_type(re->ehdr.e_type)); printf("\nEntry point 0x%jx\n", (uintmax_t)re->ehdr.e_entry); printf("There are %ju program headers, starting at offset %ju\n", (uintmax_t)phnum, (uintmax_t)re->ehdr.e_phoff); /* Dump program headers. */ printf("\nProgram Headers:\n"); if (re->ec == ELFCLASS32) printf(" %-15s%-9s%-11s%-11s%-8s%-8s%-4s%s\n", PH_HDR); else if (re->options & RE_WW) printf(" %-15s%-9s%-19s%-19s%-9s%-9s%-4s%s\n", PH_HDR); else printf(" %-15s%-19s%-19s%s\n %-19s%-20s" "%-7s%s\n", PH_HDR); for (i = 0; (size_t) i < phnum; i++) { if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { warnx("gelf_getphdr failed: %s", elf_errmsg(-1)); continue; } /* TODO: Add arch-specific segment type dump. */ if (re->ec == ELFCLASS32) printf(" %-14.14s 0x%6.6jx 0x%8.8jx 0x%8.8jx " "0x%5.5jx 0x%5.5jx %c%c%c %#jx\n", PH_CT); else if (re->options & RE_WW) printf(" %-14.14s 0x%6.6jx 0x%16.16jx 0x%16.16jx " "0x%6.6jx 0x%6.6jx %c%c%c %#jx\n", PH_CT); else printf(" %-14.14s 0x%16.16jx 0x%16.16jx 0x%16.16jx\n" " 0x%16.16jx 0x%16.16jx %c%c%c" " %#jx\n", PH_CT); if (phdr.p_type == PT_INTERP) { if ((rawfile = elf_rawfile(re->elf, NULL)) == NULL) { warnx("elf_rawfile failed: %s", elf_errmsg(-1)); continue; } printf(" [Requesting program interpreter: %s]\n", rawfile + phdr.p_offset); } } /* Dump section to segment mapping. */ if (re->shnum == 0) return; printf("\n Section to Segment mapping:\n"); printf(" Segment Sections...\n"); for (i = 0; (size_t)i < phnum; i++) { if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { warnx("gelf_getphdr failed: %s", elf_errmsg(-1)); continue; } printf(" %2.2d ", i); /* skip NULL section. */ for (j = 1; (size_t)j < re->shnum; j++) if (re->sl[j].off >= phdr.p_offset && re->sl[j].off + re->sl[j].sz <= phdr.p_offset + phdr.p_memsz) printf("%s ", re->sl[j].name); printf("\n"); } #undef PH_HDR #undef PH_CT } static char * section_flags(struct readelf *re, struct section *s) { #define BUF_SZ 256 static char buf[BUF_SZ]; int i, p, nb; p = 0; nb = re->ec == ELFCLASS32 ? 8 : 16; if (re->options & RE_T) { snprintf(buf, BUF_SZ, "[%*.*jx]: ", nb, nb, (uintmax_t)s->flags); p += nb + 4; } for (i = 0; section_flag[i].ln != NULL; i++) { if ((s->flags & section_flag[i].value) == 0) continue; if (re->options & RE_T) { snprintf(&buf[p], BUF_SZ - p, "%s, ", section_flag[i].ln); p += strlen(section_flag[i].ln) + 2; } else buf[p++] = section_flag[i].sn; } if (re->options & RE_T && p > nb + 4) p -= 2; buf[p] = '\0'; return (buf); } static void dump_shdr(struct readelf *re) { struct section *s; int i; #define S_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \ "Flg", "Lk", "Inf", "Al" #define S_HDRL "[Nr] Name", "Type", "Address", "Offset", "Size", \ "EntSize", "Flags", "Link", "Info", "Align" #define ST_HDR "[Nr] Name", "Type", "Addr", "Off", "Size", "ES", \ "Lk", "Inf", "Al", "Flags" #define ST_HDRL "[Nr] Name", "Type", "Address", "Offset", "Link", \ "Size", "EntSize", "Info", "Align", "Flags" #define S_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \ (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\ (uintmax_t)s->entsize, section_flags(re, s), \ s->link, s->info, (uintmax_t)s->align #define ST_CT i, s->name, section_type(re->ehdr.e_machine, s->type), \ (uintmax_t)s->addr, (uintmax_t)s->off, (uintmax_t)s->sz,\ (uintmax_t)s->entsize, s->link, s->info, \ (uintmax_t)s->align, section_flags(re, s) #define ST_CTL i, s->name, section_type(re->ehdr.e_machine, s->type), \ (uintmax_t)s->addr, (uintmax_t)s->off, s->link, \ (uintmax_t)s->sz, (uintmax_t)s->entsize, s->info, \ (uintmax_t)s->align, section_flags(re, s) if (re->shnum == 0) { printf("\nThere are no sections in this file.\n"); return; } printf("There are %ju section headers, starting at offset 0x%jx:\n", (uintmax_t)re->shnum, (uintmax_t)re->ehdr.e_shoff); printf("\nSection Headers:\n"); if (re->ec == ELFCLASS32) { if (re->options & RE_T) printf(" %s\n %-16s%-9s%-7s%-7s%-5s%-3s%-4s%s\n" "%12s\n", ST_HDR); else printf(" %-23s%-16s%-9s%-7s%-7s%-3s%-4s%-3s%-4s%s\n", S_HDR); } else if (re->options & RE_WW) { if (re->options & RE_T) printf(" %s\n %-16s%-17s%-7s%-7s%-5s%-3s%-4s%s\n" "%12s\n", ST_HDR); else printf(" %-23s%-16s%-17s%-7s%-7s%-3s%-4s%-3s%-4s%s\n", S_HDR); } else { if (re->options & RE_T) printf(" %s\n %-18s%-17s%-18s%s\n %-18s" "%-17s%-18s%s\n%12s\n", ST_HDRL); else printf(" %-23s%-17s%-18s%s\n %-18s%-17s%-7s%" "-6s%-6s%s\n", S_HDRL); } for (i = 0; (size_t)i < re->shnum; i++) { s = &re->sl[i]; if (re->ec == ELFCLASS32) { if (re->options & RE_T) printf(" [%2d] %s\n %-15.15s %8.8jx" " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n" " %s\n", ST_CT); else printf(" [%2d] %-17.17s %-15.15s %8.8jx" " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n", S_CT); } else if (re->options & RE_WW) { if (re->options & RE_T) printf(" [%2d] %s\n %-15.15s %16.16jx" " %6.6jx %6.6jx %2.2jx %2u %3u %2ju\n" " %s\n", ST_CT); else printf(" [%2d] %-17.17s %-15.15s %16.16jx" " %6.6jx %6.6jx %2.2jx %3s %2u %3u %2ju\n", S_CT); } else { if (re->options & RE_T) printf(" [%2d] %s\n %-15.15s %16.16jx" " %16.16jx %u\n %16.16jx %16.16jx" " %-16u %ju\n %s\n", ST_CTL); else printf(" [%2d] %-17.17s %-15.15s %16.16jx" " %8.8jx\n %16.16jx %16.16jx " "%3s %2u %3u %ju\n", S_CT); } } if ((re->options & RE_T) == 0) printf("Key to Flags:\n W (write), A (alloc)," " X (execute), M (merge), S (strings)\n" " I (info), L (link order), G (group), x (unknown)\n" " O (extra OS processing required)" " o (OS specific), p (processor specific)\n"); #undef S_HDR #undef S_HDRL #undef ST_HDR #undef ST_HDRL #undef S_CT #undef ST_CT #undef ST_CTL } static void dump_dynamic(struct readelf *re) { GElf_Dyn dyn; Elf_Data *d; struct section *s; int elferr, i, is_dynamic, j, jmax, nentries; is_dynamic = 0; for (i = 0; (size_t)i < re->shnum; i++) { s = &re->sl[i]; if (s->type != SHT_DYNAMIC) continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); continue; } if (d->d_size <= 0) continue; is_dynamic = 1; /* Determine the actual number of table entries. */ nentries = 0; jmax = (int) (s->sz / s->entsize); for (j = 0; j < jmax; j++) { if (gelf_getdyn(d, j, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); continue; } nentries ++; if (dyn.d_tag == DT_NULL) break; } printf("\nDynamic section at offset 0x%jx", (uintmax_t)s->off); printf(" contains %u entries:\n", nentries); if (re->ec == ELFCLASS32) printf("%5s%12s%28s\n", "Tag", "Type", "Name/Value"); else printf("%5s%20s%28s\n", "Tag", "Type", "Name/Value"); for (j = 0; j < nentries; j++) { if (gelf_getdyn(d, j, &dyn) != &dyn) continue; /* Dump dynamic entry type. */ if (re->ec == ELFCLASS32) printf(" 0x%8.8jx", (uintmax_t)dyn.d_tag); else printf(" 0x%16.16jx", (uintmax_t)dyn.d_tag); printf(" %-20s", dt_type(re->ehdr.e_machine, dyn.d_tag)); /* Dump dynamic entry value. */ dump_dyn_val(re, &dyn, s->link); } } if (!is_dynamic) printf("\nThere is no dynamic section in this file.\n"); } static char * timestamp(time_t ti) { static char ts[32]; struct tm *t; t = gmtime(&ti); snprintf(ts, sizeof(ts), "%04d-%02d-%02dT%02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); return (ts); } static const char * dyn_str(struct readelf *re, uint32_t stab, uint64_t d_val) { const char *name; if (stab == SHN_UNDEF) name = "ERROR"; else if ((name = elf_strptr(re->elf, stab, d_val)) == NULL) { (void) elf_errno(); /* clear error */ name = "ERROR"; } return (name); } static void dump_arch_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) { const char *name; switch (re->ehdr.e_machine) { case EM_MIPS: case EM_MIPS_RS3_LE: switch (dyn->d_tag) { case DT_MIPS_RLD_VERSION: case DT_MIPS_LOCAL_GOTNO: case DT_MIPS_CONFLICTNO: case DT_MIPS_LIBLISTNO: case DT_MIPS_SYMTABNO: case DT_MIPS_UNREFEXTNO: case DT_MIPS_GOTSYM: case DT_MIPS_HIPAGENO: case DT_MIPS_DELTA_CLASS_NO: case DT_MIPS_DELTA_INSTANCE_NO: case DT_MIPS_DELTA_RELOC_NO: case DT_MIPS_DELTA_SYM_NO: case DT_MIPS_DELTA_CLASSSYM_NO: case DT_MIPS_LOCALPAGE_GOTIDX: case DT_MIPS_LOCAL_GOTIDX: case DT_MIPS_HIDDEN_GOTIDX: case DT_MIPS_PROTECTED_GOTIDX: printf(" %ju\n", (uintmax_t) dyn->d_un.d_val); break; case DT_MIPS_ICHECKSUM: case DT_MIPS_FLAGS: case DT_MIPS_BASE_ADDRESS: case DT_MIPS_CONFLICT: case DT_MIPS_LIBLIST: case DT_MIPS_RLD_MAP: case DT_MIPS_DELTA_CLASS: case DT_MIPS_DELTA_INSTANCE: case DT_MIPS_DELTA_RELOC: case DT_MIPS_DELTA_SYM: case DT_MIPS_DELTA_CLASSSYM: case DT_MIPS_CXX_FLAGS: case DT_MIPS_PIXIE_INIT: case DT_MIPS_SYMBOL_LIB: case DT_MIPS_OPTIONS: case DT_MIPS_INTERFACE: case DT_MIPS_DYNSTR_ALIGN: case DT_MIPS_INTERFACE_SIZE: case DT_MIPS_RLD_TEXT_RESOLVE_ADDR: case DT_MIPS_COMPACT_SIZE: case DT_MIPS_GP_VALUE: case DT_MIPS_AUX_DYNAMIC: case DT_MIPS_PLTGOT: case DT_MIPS_RLD_OBJ_UPDATE: case DT_MIPS_RWPLT: printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val); break; case DT_MIPS_IVERSION: case DT_MIPS_PERF_SUFFIX: case DT_AUXILIARY: case DT_FILTER: name = dyn_str(re, stab, dyn->d_un.d_val); printf(" %s\n", name); break; case DT_MIPS_TIME_STAMP: printf(" %s\n", timestamp(dyn->d_un.d_val)); break; } break; default: printf("\n"); break; } } static void dump_dyn_val(struct readelf *re, GElf_Dyn *dyn, uint32_t stab) { const char *name; if (dyn->d_tag >= DT_LOPROC && dyn->d_tag <= DT_HIPROC) { dump_arch_dyn_val(re, dyn, stab); return; } /* These entry values are index into the string table. */ name = NULL; if (dyn->d_tag == DT_NEEDED || dyn->d_tag == DT_SONAME || dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) name = dyn_str(re, stab, dyn->d_un.d_val); switch(dyn->d_tag) { case DT_NULL: case DT_PLTGOT: case DT_HASH: case DT_STRTAB: case DT_SYMTAB: case DT_RELA: case DT_INIT: case DT_SYMBOLIC: case DT_REL: case DT_DEBUG: case DT_TEXTREL: case DT_JMPREL: case DT_FINI: case DT_VERDEF: case DT_VERNEED: case DT_VERSYM: case DT_GNU_HASH: case DT_GNU_LIBLIST: case DT_GNU_CONFLICT: printf(" 0x%jx\n", (uintmax_t) dyn->d_un.d_val); break; case DT_PLTRELSZ: case DT_RELASZ: case DT_RELAENT: case DT_STRSZ: case DT_SYMENT: case DT_RELSZ: case DT_RELENT: case DT_INIT_ARRAYSZ: case DT_FINI_ARRAYSZ: case DT_GNU_CONFLICTSZ: case DT_GNU_LIBLISTSZ: printf(" %ju (bytes)\n", (uintmax_t) dyn->d_un.d_val); break; case DT_RELACOUNT: case DT_RELCOUNT: case DT_VERDEFNUM: case DT_VERNEEDNUM: printf(" %ju\n", (uintmax_t) dyn->d_un.d_val); break; case DT_NEEDED: printf(" Shared library: [%s]\n", name); break; case DT_SONAME: printf(" Library soname: [%s]\n", name); break; case DT_RPATH: printf(" Library rpath: [%s]\n", name); break; case DT_RUNPATH: printf(" Library runpath: [%s]\n", name); break; case DT_PLTREL: printf(" %s\n", dt_type(re->ehdr.e_machine, dyn->d_un.d_val)); break; case DT_GNU_PRELINKED: printf(" %s\n", timestamp(dyn->d_un.d_val)); break; default: printf("\n"); } } static void dump_rel(struct readelf *re, struct section *s, Elf_Data *d) { GElf_Rel r; const char *symname; uint64_t symval; int i, len; #define REL_HDR "r_offset", "r_info", "r_type", "st_value", "st_name" #define REL_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ r_type(re->ehdr.e_machine, ELF32_R_TYPE(r.r_info)), \ (uintmax_t)symval, symname #define REL_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ r_type(re->ehdr.e_machine, ELF64_R_TYPE(r.r_info)), \ (uintmax_t)symval, symname printf("\nRelocation section (%s):\n", s->name); if (re->ec == ELFCLASS32) printf("%-8s %-8s %-19s %-8s %s\n", REL_HDR); else { if (re->options & RE_WW) printf("%-16s %-16s %-24s %-16s %s\n", REL_HDR); else printf("%-12s %-12s %-19s %-16s %s\n", REL_HDR); } len = d->d_size / s->entsize; for (i = 0; i < len; i++) { if (gelf_getrel(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); continue; } if (s->link >= re->shnum) { warnx("invalid section link index %u", s->link); continue; } symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); if (re->ec == ELFCLASS32) { r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info), ELF64_R_TYPE(r.r_info)); printf("%8.8jx %8.8jx %-19.19s %8.8jx %s\n", REL_CT32); } else { if (re->options & RE_WW) printf("%16.16jx %16.16jx %-24.24s" " %16.16jx %s\n", REL_CT64); else printf("%12.12jx %12.12jx %-19.19s" " %16.16jx %s\n", REL_CT64); } } #undef REL_HDR #undef REL_CT } static void dump_rela(struct readelf *re, struct section *s, Elf_Data *d) { GElf_Rela r; const char *symname; uint64_t symval; int i, len; #define RELA_HDR "r_offset", "r_info", "r_type", "st_value", \ "st_name + r_addend" #define RELA_CT32 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ r_type(re->ehdr.e_machine, ELF32_R_TYPE(r.r_info)), \ (uintmax_t)symval, symname #define RELA_CT64 (uintmax_t)r.r_offset, (uintmax_t)r.r_info, \ r_type(re->ehdr.e_machine, ELF64_R_TYPE(r.r_info)), \ (uintmax_t)symval, symname printf("\nRelocation section with addend (%s):\n", s->name); if (re->ec == ELFCLASS32) printf("%-8s %-8s %-19s %-8s %s\n", RELA_HDR); else { if (re->options & RE_WW) printf("%-16s %-16s %-24s %-16s %s\n", RELA_HDR); else printf("%-12s %-12s %-19s %-16s %s\n", RELA_HDR); } len = d->d_size / s->entsize; for (i = 0; i < len; i++) { if (gelf_getrela(d, i, &r) != &r) { warnx("gelf_getrel failed: %s", elf_errmsg(-1)); continue; } if (s->link >= re->shnum) { warnx("invalid section link index %u", s->link); continue; } symname = get_symbol_name(re, s->link, GELF_R_SYM(r.r_info)); symval = get_symbol_value(re, s->link, GELF_R_SYM(r.r_info)); if (re->ec == ELFCLASS32) { r.r_info = ELF32_R_INFO(ELF64_R_SYM(r.r_info), ELF64_R_TYPE(r.r_info)); printf("%8.8jx %8.8jx %-19.19s %8.8jx %s", RELA_CT32); printf(" + %x\n", (uint32_t) r.r_addend); } else { if (re->options & RE_WW) printf("%16.16jx %16.16jx %-24.24s" " %16.16jx %s", RELA_CT64); else printf("%12.12jx %12.12jx %-19.19s" " %16.16jx %s", RELA_CT64); printf(" + %jx\n", (uintmax_t) r.r_addend); } } #undef RELA_HDR #undef RELA_CT } static void dump_reloc(struct readelf *re) { struct section *s; Elf_Data *d; int i, elferr; for (i = 0; (size_t)i < re->shnum; i++) { s = &re->sl[i]; if (s->type == SHT_REL || s->type == SHT_RELA) { (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } if (s->type == SHT_REL) dump_rel(re, s, d); else dump_rela(re, s, d); } } } static void dump_symtab(struct readelf *re, int i) { struct section *s; Elf_Data *d; GElf_Sym sym; const char *name; int elferr, stab, j; s = &re->sl[i]; stab = s->link; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size <= 0) return; printf("Symbol table (%s)", s->name); printf(" contains %ju entries:\n", s->sz / s->entsize); printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name"); for (j = 0; (uint64_t)j < s->sz / s->entsize; j++) { if (gelf_getsym(d, j, &sym) != &sym) { warnx("gelf_getsym failed: %s", elf_errmsg(-1)); continue; } printf("%6d:", j); printf(" %16.16jx", (uintmax_t)sym.st_value); printf(" %5ju", sym.st_size); printf(" %-7s", st_type(GELF_ST_TYPE(sym.st_info))); printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info))); printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other))); printf(" %3s", st_shndx(sym.st_shndx)); if ((name = elf_strptr(re->elf, stab, sym.st_name)) != NULL) printf(" %s", name); /* Append symbol version string for SHT_DYNSYM symbol table. */ if (s->type == SHT_DYNSYM && re->ver != NULL && re->vs != NULL && re->vs[j] > 1) { if (re->vs[j] & 0x8000 || re->ver[re->vs[j] & 0x7fff].type == 0) printf("@%s (%d)", re->ver[re->vs[j] & 0x7fff].name, re->vs[j] & 0x7fff); else printf("@@%s (%d)", re->ver[re->vs[j]].name, re->vs[j]); } putchar('\n'); } } static void dump_symtabs(struct readelf *re) { GElf_Dyn dyn; Elf_Data *d; struct section *s; uint64_t dyn_off; int elferr, i; /* * If -D is specified, only dump the symbol table specified by * the DT_SYMTAB entry in the .dynamic section. */ dyn_off = 0; if (re->options & RE_DD) { s = NULL; for (i = 0; (size_t)i < re->shnum; i++) if (re->sl[i].type == SHT_DYNAMIC) { s = &re->sl[i]; break; } if (s == NULL) return; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_size <= 0) return; for (i = 0; (uint64_t)i < s->sz / s->entsize; i++) { if (gelf_getdyn(d, i, &dyn) != &dyn) { warnx("gelf_getdyn failed: %s", elf_errmsg(-1)); continue; } if (dyn.d_tag == DT_SYMTAB) { dyn_off = dyn.d_un.d_val; break; } } } /* Find and dump symbol tables. */ for (i = 0; (size_t)i < re->shnum; i++) { s = &re->sl[i]; if (s->type == SHT_SYMTAB || s->type == SHT_DYNSYM) { if (re->options & RE_DD) { if (dyn_off == s->addr) { dump_symtab(re, i); break; } } else dump_symtab(re, i); } } } static void dump_svr4_hash(struct section *s) { Elf_Data *d; uint32_t *buf; uint32_t nbucket, nchain; uint32_t *bucket, *chain; uint32_t *bl, *c, maxl, total; int elferr, i, j; /* Read and parse the content of .hash section. */ (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size < 2 * sizeof(uint32_t)) { warnx(".hash section too small"); return; } buf = d->d_buf; nbucket = buf[0]; nchain = buf[1]; if (nbucket <= 0 || nchain <= 0) { warnx("Malformed .hash section"); return; } if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { warnx("Malformed .hash section"); return; } bucket = &buf[2]; chain = &buf[2 + nbucket]; maxl = 0; if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint32_t)i < nbucket; i++) for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j]) if (++bl[i] > maxl) maxl = bl[i]; if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint32_t)i < nbucket; i++) c[bl[i]]++; printf("\nHistogram for bucket list length (total of %u buckets):\n", nbucket); printf(" Length\tNumber\t\t%% of total\tCoverage\n"); total = 0; for (i = 0; (uint32_t)i <= maxl; i++) { total += c[i] * i; printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i], c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); } free(c); free(bl); } static void dump_svr4_hash64(struct readelf *re, struct section *s) { Elf_Data *d, dst; uint64_t *buf; uint64_t nbucket, nchain; uint64_t *bucket, *chain; uint64_t *bl, *c, maxl, total; int elferr, i, j; /* * ALPHA uses 64-bit hash entries. Since libelf assumes that * .hash section contains only 32-bit entry, an explicit * gelf_xlatetom is needed here. */ (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_rawdata failed: %s", elf_errmsg(elferr)); return; } d->d_type = ELF_T_XWORD; memcpy(&dst, d, sizeof(Elf_Data)); if (gelf_xlatetom(re->elf, &dst, d, re->ehdr.e_ident[EI_DATA]) != &dst) { warnx("gelf_xlatetom failed: %s", elf_errmsg(-1)); return; } if (dst.d_size < 2 * sizeof(uint64_t)) { warnx(".hash section too small"); return; } buf = dst.d_buf; nbucket = buf[0]; nchain = buf[1]; if (nbucket <= 0 || nchain <= 0) { warnx("Malformed .hash section"); return; } if (d->d_size != (nbucket + nchain + 2) * sizeof(uint32_t)) { warnx("Malformed .hash section"); return; } bucket = &buf[2]; chain = &buf[2 + nbucket]; maxl = 0; if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint32_t)i < nbucket; i++) for (j = bucket[i]; j > 0 && (uint32_t)j < nchain; j = chain[j]) if (++bl[i] > maxl) maxl = bl[i]; if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint64_t)i < nbucket; i++) c[bl[i]]++; printf("Histogram for bucket list length (total of %ju buckets):\n", (uintmax_t)nbucket); printf(" Length\tNumber\t\t%% of total\tCoverage\n"); total = 0; for (i = 0; (uint64_t)i <= maxl; i++) { total += c[i] * i; printf("%7u\t%-10ju\t(%5.1f%%)\t%5.1f%%\n", i, (uintmax_t)c[i], c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); } free(c); free(bl); } static void dump_gnu_hash(struct readelf *re, struct section *s) { struct section *ds; Elf_Data *d; uint32_t *buf; uint32_t *bucket, *chain; uint32_t nbucket, nchain, symndx, maskwords; uint32_t *bl, *c, maxl, total; int elferr, dynsymcount, i, j; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size < 4 * sizeof(uint32_t)) { warnx(".gnu.hash section too small"); return; } buf = d->d_buf; nbucket = buf[0]; symndx = buf[1]; maskwords = buf[2]; buf += 4; ds = &re->sl[s->link]; dynsymcount = ds->sz / ds->entsize; nchain = dynsymcount - symndx; if (d->d_size != 4 * sizeof(uint32_t) + maskwords * (re->ec == ELFCLASS32 ? sizeof(uint32_t) : sizeof(uint64_t)) + (nbucket + nchain) * sizeof(uint32_t)) { warnx("Malformed .gnu.hash section"); return; } bucket = buf + (re->ec == ELFCLASS32 ? maskwords : maskwords * 2); chain = bucket + nbucket; maxl = 0; if ((bl = calloc(nbucket, sizeof(*bl))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint32_t)i < nbucket; i++) for (j = bucket[i]; j > 0 && (uint32_t)j - symndx < nchain; j++) { if (++bl[i] > maxl) maxl = bl[i]; if (chain[j - symndx] & 1) break; } if ((c = calloc(maxl + 1, sizeof(*c))) == NULL) errx(EXIT_FAILURE, "calloc failed"); for (i = 0; (uint32_t)i < nbucket; i++) c[bl[i]]++; printf("Histogram for bucket list length (total of %u buckets):\n", nbucket); printf(" Length\tNumber\t\t%% of total\tCoverage\n"); total = 0; for (i = 0; (uint32_t)i <= maxl; i++) { total += c[i] * i; printf("%7u\t%-10u\t(%5.1f%%)\t%5.1f%%\n", i, c[i], c[i] * 100.0 / nbucket, total * 100.0 / (nchain - 1)); } free(c); free(bl); } static void dump_hash(struct readelf *re) { struct section *s; int i; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type == SHT_HASH || s->type == SHT_GNU_HASH) { if (s->type == SHT_GNU_HASH) dump_gnu_hash(re, s); else if (re->ehdr.e_machine == EM_ALPHA && s->entsize == 8) dump_svr4_hash64(re, s); else dump_svr4_hash(s); } } } static void dump_notes(struct readelf *re) { struct section *s; const char *rawfile; GElf_Phdr phdr; Elf_Data *d; size_t phnum; int i, elferr; if (re->ehdr.e_type == ET_CORE) { /* * Search program headers in the core file for * PT_NOTE entry. */ if (elf_getphnum(re->elf, &phnum) == 0) { warnx("elf_getphnum failed: %s", elf_errmsg(-1)); return; } if (phnum == 0) return; if ((rawfile = elf_rawfile(re->elf, NULL)) == NULL) { warnx("elf_rawfile failed: %s", elf_errmsg(-1)); return; } for (i = 0; (size_t) i < phnum; i++) { if (gelf_getphdr(re->elf, i, &phdr) != &phdr) { warnx("gelf_getphdr failed: %s", elf_errmsg(-1)); continue; } if (phdr.p_type == PT_NOTE) dump_notes_content(re, rawfile + phdr.p_offset, phdr.p_filesz, phdr.p_offset); } } else { /* * For objects other than core files, Search for * SHT_NOTE sections. */ for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type == SHT_NOTE) { (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } dump_notes_content(re, d->d_buf, d->d_size, s->off); } } } } static void dump_notes_content(struct readelf *re, const char *buf, size_t sz, off_t off) { Elf_Note *note; const char *end, *name; printf("\nNotes at offset %#010jx with length %#010jx:\n", (uintmax_t) off, (uintmax_t) sz); printf(" %-13s %-15s %s\n", "Owner", "Data size", "Description"); end = buf + sz; while (buf < end) { if (buf + sizeof(*note) > end) { warnx("invalid note header"); return; } note = (Elf_Note *)(uintptr_t) buf; name = (char *)(uintptr_t)(note + 1); /* * The name field is required to be nul-terminated, and * n_namesz includes the terminating nul in observed * implementations (contrary to the ELF-64 spec). A special * case is needed for cores generated by some older Linux * versions, which write a note named "CORE" without a nul * terminator and n_namesz = 4. */ if (note->n_namesz == 0) name = ""; else if (note->n_namesz == 4 && strncmp(name, "CORE", 4) == 0) name = "CORE"; else if (strnlen(name, note->n_namesz) >= note->n_namesz) name = ""; printf(" %-13s %#010jx", name, (uintmax_t) note->n_descsz); printf(" %s\n", note_type(name, re->ehdr.e_type, note->n_type)); buf += sizeof(Elf_Note) + roundup2(note->n_namesz, 4) + roundup2(note->n_descsz, 4); } } /* * Symbol versioning sections are the same for 32bit and 64bit * ELF objects. */ #define Elf_Verdef Elf32_Verdef #define Elf_Verdaux Elf32_Verdaux #define Elf_Verneed Elf32_Verneed #define Elf_Vernaux Elf32_Vernaux #define SAVE_VERSION_NAME(x, n, t) \ do { \ while (x >= re->ver_sz) { \ nv = realloc(re->ver, \ sizeof(*re->ver) * re->ver_sz * 2); \ if (nv == NULL) { \ warn("realloc failed"); \ free(re->ver); \ return; \ } \ re->ver = nv; \ for (i = re->ver_sz; i < re->ver_sz * 2; i++) { \ re->ver[i].name = NULL; \ re->ver[i].type = 0; \ } \ re->ver_sz *= 2; \ } \ if (x > 1) { \ re->ver[x].name = n; \ re->ver[x].type = t; \ } \ } while (0) static void dump_verdef(struct readelf *re, int dump) { struct section *s; struct symver *nv; Elf_Data *d; Elf_Verdef *vd; Elf_Verdaux *vda; uint8_t *buf, *end, *buf2; const char *name; int elferr, i, j; if ((s = re->vd_s) == NULL) return; if (re->ver == NULL) { re->ver_sz = 16; if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) == NULL) { warn("calloc failed"); return; } re->ver[0].name = "*local*"; re->ver[1].name = "*global*"; } if (dump) printf("\nVersion definition section (%s):\n", s->name); (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size == 0) return; buf = d->d_buf; end = buf + d->d_size; while (buf + sizeof(Elf_Verdef) <= end) { vd = (Elf_Verdef *) (uintptr_t) buf; if (dump) { printf(" 0x%4.4lx", (unsigned long) (buf - (uint8_t *)d->d_buf)); printf(" vd_version: %u vd_flags: %d" " vd_ndx: %u vd_cnt: %u", vd->vd_version, vd->vd_flags, vd->vd_ndx, vd->vd_cnt); } buf2 = buf + vd->vd_aux; j = 0; while (buf2 + sizeof(Elf_Verdaux) <= end && j < vd->vd_cnt) { vda = (Elf_Verdaux *) (uintptr_t) buf2; name = get_string(re, s->link, vda->vda_name); if (j == 0) { if (dump) printf(" vda_name: %s\n", name); SAVE_VERSION_NAME((int)vd->vd_ndx, name, 1); } else if (dump) printf(" 0x%4.4lx parent: %s\n", (unsigned long) (buf2 - (uint8_t *)d->d_buf), name); if (vda->vda_next == 0) break; buf2 += vda->vda_next; j++; } if (vd->vd_next == 0) break; buf += vd->vd_next; } } static void dump_verneed(struct readelf *re, int dump) { struct section *s; struct symver *nv; Elf_Data *d; Elf_Verneed *vn; Elf_Vernaux *vna; uint8_t *buf, *end, *buf2; const char *name; int elferr, i, j; if ((s = re->vn_s) == NULL) return; if (re->ver == NULL) { re->ver_sz = 16; if ((re->ver = calloc(re->ver_sz, sizeof(*re->ver))) == NULL) { warn("calloc failed"); return; } re->ver[0].name = "*local*"; re->ver[1].name = "*global*"; } if (dump) printf("\nVersion needed section (%s):\n", s->name); (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size == 0) return; buf = d->d_buf; end = buf + d->d_size; while (buf + sizeof(Elf_Verneed) <= end) { vn = (Elf_Verneed *) (uintptr_t) buf; if (dump) { printf(" 0x%4.4lx", (unsigned long) (buf - (uint8_t *)d->d_buf)); printf(" vn_version: %u vn_file: %s vn_cnt: %u\n", vn->vn_version, get_string(re, s->link, vn->vn_file), vn->vn_cnt); } buf2 = buf + vn->vn_aux; j = 0; while (buf2 + sizeof(Elf_Vernaux) <= end && j < vn->vn_cnt) { vna = (Elf32_Vernaux *) (uintptr_t) buf2; if (dump) printf(" 0x%4.4lx", (unsigned long) (buf2 - (uint8_t *)d->d_buf)); name = get_string(re, s->link, vna->vna_name); if (dump) printf(" vna_name: %s vna_flags: %u" " vna_other: %u\n", name, vna->vna_flags, vna->vna_other); SAVE_VERSION_NAME((int)vna->vna_other, name, 0); if (vna->vna_next == 0) break; buf2 += vna->vna_next; j++; } if (vn->vn_next == 0) break; buf += vn->vn_next; } } static void dump_versym(struct readelf *re) { int i; if (re->vs_s == NULL || re->ver == NULL || re->vs == NULL) return; printf("\nVersion symbol section (%s):\n", re->vs_s->name); for (i = 0; i < re->vs_sz; i++) { if ((i & 3) == 0) { if (i > 0) putchar('\n'); printf(" %03x:", i); } if (re->vs[i] & 0x8000) printf(" %3xh %-12s ", re->vs[i] & 0x7fff, re->ver[re->vs[i] & 0x7fff].name); else printf(" %3x %-12s ", re->vs[i], re->ver[re->vs[i]].name); } putchar('\n'); } static void dump_ver(struct readelf *re) { if (re->vs_s && re->ver && re->vs) dump_versym(re); if (re->vd_s) dump_verdef(re, 1); if (re->vn_s) dump_verneed(re, 1); } static void search_ver(struct readelf *re) { struct section *s; Elf_Data *d; int elferr, i; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type == SHT_SUNW_versym) re->vs_s = s; if (s->type == SHT_SUNW_verneed) re->vn_s = s; if (s->type == SHT_SUNW_verdef) re->vd_s = s; } if (re->vd_s) dump_verdef(re, 0); if (re->vn_s) dump_verneed(re, 0); if (re->vs_s && re->ver != NULL) { (void) elf_errno(); if ((d = elf_getdata(re->vs_s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size == 0) return; re->vs = d->d_buf; re->vs_sz = d->d_size / sizeof(Elf32_Half); } } #undef Elf_Verdef #undef Elf_Verdaux #undef Elf_Verneed #undef Elf_Vernaux #undef SAVE_VERSION_NAME /* * Elf32_Lib and Elf64_Lib are identical. */ #define Elf_Lib Elf32_Lib static void dump_liblist(struct readelf *re) { struct section *s; struct tm *t; time_t ti; char tbuf[20]; Elf_Data *d; Elf_Lib *lib; int i, j, k, elferr, first; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type != SHT_GNU_LIBLIST) continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } if (d->d_size <= 0) continue; lib = d->d_buf; printf("\nLibrary list section '%s' ", s->name); printf("contains %ju entries:\n", s->sz / s->entsize); printf("%12s%24s%18s%10s%6s\n", "Library", "Time Stamp", "Checksum", "Version", "Flags"); for (j = 0; (uint64_t) j < s->sz / s->entsize; j++) { printf("%3d: ", j); printf("%-20.20s ", get_string(re, s->link, lib->l_name)); ti = lib->l_time_stamp; t = gmtime(&ti); snprintf(tbuf, sizeof(tbuf), "%04d-%02d-%02dT%02d:%02d" ":%2d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); printf("%-19.19s ", tbuf); printf("0x%08x ", lib->l_checksum); printf("%-7d %#x", lib->l_version, lib->l_flags); if (lib->l_flags != 0) { first = 1; putchar('('); for (k = 0; l_flag[k].name != NULL; k++) { if ((l_flag[k].value & lib->l_flags) == 0) continue; if (!first) putchar(','); else first = 0; printf("%s", l_flag[k].name); } putchar(')'); } putchar('\n'); lib++; } } } #undef Elf_Lib static uint8_t * dump_unknown_tag(uint64_t tag, uint8_t *p) { uint64_t val; /* * According to ARM EABI: For tags > 32, even numbered tags have * a ULEB128 param and odd numbered ones have NUL-terminated * string param. This rule probably also applies for tags <= 32 * if the object arch is not ARM. */ printf(" Tag_unknown_%ju: ", (uintmax_t) tag); if (tag & 1) { printf("%s\n", (char *) p); p += strlen((char *) p) + 1; } else { val = _decode_uleb128(&p); printf("%ju\n", (uintmax_t) val); } return (p); } static uint8_t * dump_compatibility_tag(uint8_t *p) { uint64_t val; val = _decode_uleb128(&p); printf("flag = %ju, vendor = %s\n", val, p); p += strlen((char *) p) + 1; return (p); } static void dump_arm_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) { uint64_t tag, val; size_t i; int found, desc; (void) re; while (p < pe) { tag = _decode_uleb128(&p); found = desc = 0; for (i = 0; i < sizeof(aeabi_tags) / sizeof(aeabi_tags[0]); i++) { if (tag == aeabi_tags[i].tag) { found = 1; printf(" %s: ", aeabi_tags[i].s_tag); if (aeabi_tags[i].get_desc) { desc = 1; val = _decode_uleb128(&p); printf("%s\n", aeabi_tags[i].get_desc(val)); } break; } if (tag < aeabi_tags[i].tag) break; } if (!found) { p = dump_unknown_tag(tag, p); continue; } if (desc) continue; switch (tag) { case 4: /* Tag_CPU_raw_name */ case 5: /* Tag_CPU_name */ case 67: /* Tag_conformance */ printf("%s\n", (char *) p); p += strlen((char *) p) + 1; break; case 32: /* Tag_compatibility */ p = dump_compatibility_tag(p); break; case 64: /* Tag_nodefaults */ /* ignored, written as 0. */ (void) _decode_uleb128(&p); printf("True\n"); break; case 65: /* Tag_also_compatible_with */ val = _decode_uleb128(&p); /* Must be Tag_CPU_arch */ if (val != 6) { printf("unknown\n"); break; } val = _decode_uleb128(&p); printf("%s\n", aeabi_cpu_arch(val)); /* Skip NUL terminator. */ p++; break; default: putchar('\n'); break; } } } #ifndef Tag_GNU_MIPS_ABI_FP #define Tag_GNU_MIPS_ABI_FP 4 #endif static void dump_mips_attributes(struct readelf *re, uint8_t *p, uint8_t *pe) { uint64_t tag, val; (void) re; while (p < pe) { tag = _decode_uleb128(&p); switch (tag) { case Tag_GNU_MIPS_ABI_FP: val = _decode_uleb128(&p); printf(" Tag_GNU_MIPS_ABI_FP: %s\n", mips_abi_fp(val)); break; case 32: /* Tag_compatibility */ p = dump_compatibility_tag(p); break; default: p = dump_unknown_tag(tag, p); break; } } } #ifndef Tag_GNU_Power_ABI_FP #define Tag_GNU_Power_ABI_FP 4 #endif #ifndef Tag_GNU_Power_ABI_Vector #define Tag_GNU_Power_ABI_Vector 8 #endif static void dump_ppc_attributes(uint8_t *p, uint8_t *pe) { uint64_t tag, val; while (p < pe) { tag = _decode_uleb128(&p); switch (tag) { case Tag_GNU_Power_ABI_FP: val = _decode_uleb128(&p); printf(" Tag_GNU_Power_ABI_FP: %s\n", ppc_abi_fp(val)); break; case Tag_GNU_Power_ABI_Vector: val = _decode_uleb128(&p); printf(" Tag_GNU_Power_ABI_Vector: %s\n", ppc_abi_vector(val)); break; case 32: /* Tag_compatibility */ p = dump_compatibility_tag(p); break; default: p = dump_unknown_tag(tag, p); break; } } } static void dump_attributes(struct readelf *re) { struct section *s; Elf_Data *d; uint8_t *p, *sp; size_t len, seclen, nlen, sublen; uint64_t val; int tag, i, elferr; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->type != SHT_GNU_ATTRIBUTES && (re->ehdr.e_machine != EM_ARM || s->type != SHT_LOPROC + 3)) continue; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_rawdata failed: %s", elf_errmsg(elferr)); continue; } if (d->d_size <= 0) continue; p = d->d_buf; if (*p != 'A') { printf("Unknown Attribute Section Format: %c\n", (char) *p); continue; } len = d->d_size - 1; p++; while (len > 0) { if (len < 4) { warnx("truncated attribute section length"); break; } seclen = re->dw_decode(&p, 4); if (seclen > len) { warnx("invalid attribute section length"); break; } len -= seclen; nlen = strlen((char *) p) + 1; if (nlen + 4 > seclen) { warnx("invalid attribute section name"); break; } printf("Attribute Section: %s\n", (char *) p); p += nlen; seclen -= nlen + 4; while (seclen > 0) { sp = p; tag = *p++; sublen = re->dw_decode(&p, 4); if (sublen > seclen) { warnx("invalid attribute sub-section" " length"); break; } seclen -= sublen; printf("%s", top_tag(tag)); if (tag == 2 || tag == 3) { putchar(':'); for (;;) { val = _decode_uleb128(&p); if (val == 0) break; printf(" %ju", (uintmax_t) val); } } putchar('\n'); if (re->ehdr.e_machine == EM_ARM && s->type == SHT_LOPROC + 3) dump_arm_attributes(re, p, sp + sublen); else if (re->ehdr.e_machine == EM_MIPS || re->ehdr.e_machine == EM_MIPS_RS3_LE) dump_mips_attributes(re, p, sp + sublen); else if (re->ehdr.e_machine == EM_PPC) dump_ppc_attributes(p, sp + sublen); p = sp + sublen; } } } } static void dump_mips_specific_info(struct readelf *re) { struct section *s; int i, options_found; options_found = 0; s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && (!strcmp(s->name, ".MIPS.options") || (s->type == SHT_MIPS_OPTIONS))) { dump_mips_options(re, s); options_found = 1; } } /* * According to SGI mips64 spec, .reginfo should be ignored if * .MIPS.options section is present. */ if (!options_found) { for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && (!strcmp(s->name, ".reginfo") || (s->type == SHT_MIPS_REGINFO))) dump_mips_reginfo(re, s); } } } static void dump_mips_reginfo(struct readelf *re, struct section *s) { Elf_Data *d; int elferr; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_rawdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size <= 0) return; printf("\nSection '%s' contains %ju entries:\n", s->name, s->sz / s->entsize); dump_mips_odk_reginfo(re, d->d_buf, d->d_size); } static void dump_mips_options(struct readelf *re, struct section *s) { Elf_Data *d; uint32_t info; uint16_t sndx; uint8_t *p, *pe; uint8_t kind, size; int elferr; (void) elf_errno(); if ((d = elf_rawdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_rawdata failed: %s", elf_errmsg(elferr)); return; } if (d->d_size == 0) return; printf("\nSection %s contains:\n", s->name); p = d->d_buf; pe = p + d->d_size; while (p < pe) { kind = re->dw_decode(&p, 1); size = re->dw_decode(&p, 1); sndx = re->dw_decode(&p, 2); info = re->dw_decode(&p, 4); switch (kind) { case ODK_REGINFO: dump_mips_odk_reginfo(re, p, size - 8); break; case ODK_EXCEPTIONS: printf(" EXCEPTIONS FPU_MIN: %#x\n", info & OEX_FPU_MIN); printf("%11.11s FPU_MAX: %#x\n", "", info & OEX_FPU_MAX); dump_mips_option_flags("", mips_exceptions_option, info); break; case ODK_PAD: printf(" %-10.10s section: %ju\n", "OPAD", (uintmax_t) sndx); dump_mips_option_flags("", mips_pad_option, info); break; case ODK_HWPATCH: dump_mips_option_flags("HWPATCH", mips_hwpatch_option, info); break; case ODK_HWAND: dump_mips_option_flags("HWAND", mips_hwa_option, info); break; case ODK_HWOR: dump_mips_option_flags("HWOR", mips_hwo_option, info); break; case ODK_FILL: printf(" %-10.10s %#jx\n", "FILL", (uintmax_t) info); break; case ODK_TAGS: printf(" %-10.10s\n", "TAGS"); break; case ODK_GP_GROUP: printf(" %-10.10s GP group number: %#x\n", "GP_GROUP", info & 0xFFFF); if (info & 0x10000) printf(" %-10.10s GP group is " "self-contained\n", ""); break; case ODK_IDENT: printf(" %-10.10s default GP group number: %#x\n", "IDENT", info & 0xFFFF); if (info & 0x10000) printf(" %-10.10s default GP group is " "self-contained\n", ""); break; case ODK_PAGESIZE: printf(" %-10.10s\n", "PAGESIZE"); break; default: break; } p += size - 8; } } static void dump_mips_option_flags(const char *name, struct mips_option *opt, uint64_t info) { int first; first = 1; for (; opt->desc != NULL; opt++) { if (info & opt->flag) { printf(" %-10.10s %s\n", first ? name : "", opt->desc); first = 0; } } } static void dump_mips_odk_reginfo(struct readelf *re, uint8_t *p, size_t sz) { uint32_t ri_gprmask; uint32_t ri_cprmask[4]; uint64_t ri_gp_value; uint8_t *pe; int i; pe = p + sz; while (p < pe) { ri_gprmask = re->dw_decode(&p, 4); /* Skip ri_pad padding field for mips64. */ if (re->ec == ELFCLASS64) re->dw_decode(&p, 4); for (i = 0; i < 4; i++) ri_cprmask[i] = re->dw_decode(&p, 4); if (re->ec == ELFCLASS32) ri_gp_value = re->dw_decode(&p, 4); else ri_gp_value = re->dw_decode(&p, 8); printf(" %s ", option_kind(ODK_REGINFO)); printf("ri_gprmask: 0x%08jx\n", (uintmax_t) ri_gprmask); for (i = 0; i < 4; i++) printf("%11.11s ri_cprmask[%d]: 0x%08jx\n", "", i, (uintmax_t) ri_cprmask[i]); printf("%12.12s", ""); printf("ri_gp_value: %#jx\n", (uintmax_t) ri_gp_value); } } static void dump_arch_specific_info(struct readelf *re) { dump_liblist(re); dump_attributes(re); switch (re->ehdr.e_machine) { case EM_MIPS: case EM_MIPS_RS3_LE: dump_mips_specific_info(re); default: break; } } static const char * dwarf_regname(struct readelf *re, unsigned int num) { static char rx[32]; const char *rn; if ((rn = dwarf_reg(re->ehdr.e_machine, num)) != NULL) return (rn); snprintf(rx, sizeof(rx), "r%u", num); return (rx); } static void dump_dwarf_line(struct readelf *re) { struct section *s; Dwarf_Die die; Dwarf_Error de; Dwarf_Half tag, version, pointer_size; Dwarf_Unsigned offset, endoff, length, hdrlen, dirndx, mtime, fsize; Dwarf_Small minlen, defstmt, lrange, opbase, oplen; Elf_Data *d; char *pn; uint64_t address, file, line, column, isa, opsize, udelta; int64_t sdelta; uint8_t *p, *pe; int8_t lbase; int i, is_stmt, dwarf_size, elferr, ret; printf("\nDump of debug contents of section .debug_line:\n"); s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && !strcmp(s->name, ".debug_line")) break; } if ((size_t) i >= re->shnum) return; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_size <= 0) return; while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; while (dwarf_siblingof(re->dbg, die, &die, &de) == DW_DLV_OK) { if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); return; } /* XXX: What about DW_TAG_partial_unit? */ if (tag == DW_TAG_compile_unit) break; } if (die == NULL) { warnx("could not find DW_TAG_compile_unit die"); return; } if (dwarf_attrval_unsigned(die, DW_AT_stmt_list, &offset, &de) != DW_DLV_OK) continue; length = re->dw_read(d, &offset, 4); if (length == 0xffffffff) { dwarf_size = 8; length = re->dw_read(d, &offset, 8); } else dwarf_size = 4; if (length > d->d_size - offset) { warnx("invalid .dwarf_line section"); continue; } endoff = offset + length; version = re->dw_read(d, &offset, 2); hdrlen = re->dw_read(d, &offset, dwarf_size); minlen = re->dw_read(d, &offset, 1); defstmt = re->dw_read(d, &offset, 1); lbase = re->dw_read(d, &offset, 1); lrange = re->dw_read(d, &offset, 1); opbase = re->dw_read(d, &offset, 1); printf("\n"); printf(" Length:\t\t\t%ju\n", (uintmax_t) length); printf(" DWARF version:\t\t%u\n", version); printf(" Prologue Length:\t\t%ju\n", (uintmax_t) hdrlen); printf(" Minimum Instruction Length:\t%u\n", minlen); printf(" Initial value of 'is_stmt':\t%u\n", defstmt); printf(" Line Base:\t\t\t%d\n", lbase); printf(" Line Range:\t\t\t%u\n", lrange); printf(" Opcode Base:\t\t\t%u\n", opbase); (void) dwarf_get_address_size(re->dbg, &pointer_size, &de); printf(" (Pointer size:\t\t%u)\n", pointer_size); printf("\n"); printf(" Opcodes:\n"); for (i = 1; i < opbase; i++) { oplen = re->dw_read(d, &offset, 1); printf(" Opcode %d has %u args\n", i, oplen); } printf("\n"); printf(" The Directory Table:\n"); p = (uint8_t *) d->d_buf + offset; while (*p != '\0') { printf(" %s\n", (char *) p); p += strlen((char *) p) + 1; } p++; printf("\n"); printf(" The File Name Table:\n"); printf(" Entry\tDir\tTime\tSize\tName\n"); i = 0; while (*p != '\0') { i++; pn = (char *) p; p += strlen(pn) + 1; dirndx = _decode_uleb128(&p); mtime = _decode_uleb128(&p); fsize = _decode_uleb128(&p); printf(" %d\t%ju\t%ju\t%ju\t%s\n", i, (uintmax_t) dirndx, (uintmax_t) mtime, (uintmax_t) fsize, pn); } #define RESET_REGISTERS \ do { \ address = 0; \ file = 1; \ line = 1; \ column = 0; \ is_stmt = defstmt; \ } while(0) #define LINE(x) (lbase + (((x) - opbase) % lrange)) #define ADDRESS(x) ((((x) - opbase) / lrange) * minlen) p++; pe = (uint8_t *) d->d_buf + endoff; printf("\n"); printf(" Line Number Statements:\n"); RESET_REGISTERS; while (p < pe) { if (*p == 0) { /* * Extended Opcodes. */ p++; opsize = _decode_uleb128(&p); printf(" Extended opcode %u: ", *p); switch (*p) { case DW_LNE_end_sequence: p++; RESET_REGISTERS; printf("End of Sequence\n"); break; case DW_LNE_set_address: p++; address = re->dw_decode(&p, pointer_size); printf("set Address to %#jx\n", (uintmax_t) address); break; case DW_LNE_define_file: p++; pn = (char *) p; p += strlen(pn) + 1; dirndx = _decode_uleb128(&p); mtime = _decode_uleb128(&p); fsize = _decode_uleb128(&p); printf("define new file: %s\n", pn); break; default: /* Unrecognized extened opcodes. */ p += opsize; printf("unknown opcode\n"); } } else if (*p > 0 && *p < opbase) { /* * Standard Opcodes. */ switch(*p++) { case DW_LNS_copy: printf(" Copy\n"); break; case DW_LNS_advance_pc: udelta = _decode_uleb128(&p) * minlen; address += udelta; printf(" Advance PC by %ju to %#jx\n", (uintmax_t) udelta, (uintmax_t) address); break; case DW_LNS_advance_line: sdelta = _decode_sleb128(&p); line += sdelta; printf(" Advance Line by %jd to %ju\n", (intmax_t) sdelta, (uintmax_t) line); break; case DW_LNS_set_file: file = _decode_uleb128(&p); printf(" Set File to %ju\n", (uintmax_t) file); break; case DW_LNS_set_column: column = _decode_uleb128(&p); printf(" Set Column to %ju\n", (uintmax_t) column); break; case DW_LNS_negate_stmt: is_stmt = !is_stmt; printf(" Set is_stmt to %d\n", is_stmt); break; case DW_LNS_set_basic_block: printf(" Set basic block flag\n"); break; case DW_LNS_const_add_pc: address += ADDRESS(255); printf(" Advance PC by constant %ju" " to %#jx\n", (uintmax_t) ADDRESS(255), (uintmax_t) address); break; case DW_LNS_fixed_advance_pc: udelta = re->dw_decode(&p, 2); address += udelta; printf(" Advance PC by fixed value " "%ju to %#jx\n", (uintmax_t) udelta, (uintmax_t) address); break; case DW_LNS_set_prologue_end: printf(" Set prologue end flag\n"); break; case DW_LNS_set_epilogue_begin: printf(" Set epilogue begin flag\n"); break; case DW_LNS_set_isa: isa = _decode_uleb128(&p); printf(" Set isa to %ju\n", isa); break; default: /* Unrecognized extended opcodes. */ printf(" Unknown extended opcode %u\n", *(p - 1)); break; } } else { /* * Special Opcodes. */ line += LINE(*p); address += ADDRESS(*p); printf(" Special opcode %u: advance Address " "by %ju to %#jx and Line by %jd to %ju\n", *p - opbase, (uintmax_t) ADDRESS(*p), (uintmax_t) address, (intmax_t) LINE(*p), (uintmax_t) line); p++; } } } if (ret == DW_DLV_ERROR) warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); #undef RESET_REGISTERS #undef LINE #undef ADDRESS } static void dump_dwarf_line_decoded(struct readelf *re) { Dwarf_Die die; Dwarf_Line *linebuf, ln; Dwarf_Addr lineaddr; Dwarf_Signed linecount, srccount; Dwarf_Unsigned lineno, fn; Dwarf_Error de; const char *dir, *file; char **srcfiles; int i, ret; printf("Decoded dump of debug contents of section .debug_line:\n\n"); while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { if (dwarf_siblingof(re->dbg, NULL, &die, &de) != DW_DLV_OK) continue; if (dwarf_attrval_string(die, DW_AT_name, &file, &de) != DW_DLV_OK) file = NULL; if (dwarf_attrval_string(die, DW_AT_comp_dir, &dir, &de) != DW_DLV_OK) dir = NULL; printf("CU: "); if (dir && file) printf("%s/", dir); if (file) printf("%s", file); putchar('\n'); printf("%-37s %11s %s\n", "Filename", "Line Number", "Starting Address"); if (dwarf_srclines(die, &linebuf, &linecount, &de) != DW_DLV_OK) continue; if (dwarf_srcfiles(die, &srcfiles, &srccount, &de) != DW_DLV_OK) continue; for (i = 0; i < linecount; i++) { ln = linebuf[i]; if (dwarf_line_srcfileno(ln, &fn, &de) != DW_DLV_OK) continue; if (dwarf_lineno(ln, &lineno, &de) != DW_DLV_OK) continue; if (dwarf_lineaddr(ln, &lineaddr, &de) != DW_DLV_OK) continue; printf("%-37s %11ju %#18jx\n", basename(srcfiles[fn - 1]), (uintmax_t) lineno, (uintmax_t) lineaddr); } putchar('\n'); } } static void dump_dwarf_die(struct readelf *re, Dwarf_Die die, int level) { Dwarf_Attribute *attr_list; Dwarf_Die ret_die; Dwarf_Off dieoff, cuoff, culen, attroff; Dwarf_Unsigned ate, lang, v_udata, v_sig; Dwarf_Signed attr_count, v_sdata; Dwarf_Off v_off; Dwarf_Addr v_addr; Dwarf_Half tag, attr, form; Dwarf_Block *v_block; Dwarf_Bool v_bool, is_info; Dwarf_Sig8 v_sig8; Dwarf_Error de; Dwarf_Ptr v_expr; const char *tag_str, *attr_str, *ate_str, *lang_str; char unk_tag[32], unk_attr[32]; char *v_str; uint8_t *b, *p; int i, j, abc, ret; if (dwarf_dieoffset(die, &dieoff, &de) != DW_DLV_OK) { warnx("dwarf_dieoffset failed: %s", dwarf_errmsg(de)); goto cont_search; } printf(" <%d><%jx>: ", level, (uintmax_t) dieoff); if (dwarf_die_CU_offset_range(die, &cuoff, &culen, &de) != DW_DLV_OK) { warnx("dwarf_die_CU_offset_range failed: %s", dwarf_errmsg(de)); cuoff = 0; } abc = dwarf_die_abbrev_code(die); if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); goto cont_search; } if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) { snprintf(unk_tag, sizeof(unk_tag), "[Unknown Tag: %#x]", tag); tag_str = unk_tag; } printf("Abbrev Number: %d (%s)\n", abc, tag_str); if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != DW_DLV_OK) { if (ret == DW_DLV_ERROR) warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); goto cont_search; } for (i = 0; i < attr_count; i++) { if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) { warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) { snprintf(unk_attr, sizeof(unk_attr), "[Unknown AT: %#x]", attr); attr_str = unk_attr; } if (dwarf_attroffset(attr_list[i], &attroff, &de) != DW_DLV_OK) { warnx("dwarf_attroffset failed: %s", dwarf_errmsg(de)); attroff = 0; } printf(" <%jx> %-18s: ", (uintmax_t) attroff, attr_str); switch (form) { case DW_FORM_ref_addr: case DW_FORM_sec_offset: if (dwarf_global_formref(attr_list[i], &v_off, &de) != DW_DLV_OK) { warnx("dwarf_global_formref failed: %s", dwarf_errmsg(de)); continue; } if (form == DW_FORM_ref_addr) printf("<0x%jx>", (uintmax_t) v_off); else printf("0x%jx", (uintmax_t) v_off); break; case DW_FORM_ref1: case DW_FORM_ref2: case DW_FORM_ref4: case DW_FORM_ref8: case DW_FORM_ref_udata: if (dwarf_formref(attr_list[i], &v_off, &de) != DW_DLV_OK) { warnx("dwarf_formref failed: %s", dwarf_errmsg(de)); continue; } v_off += cuoff; printf("<0x%jx>", (uintmax_t) v_off); break; case DW_FORM_addr: if (dwarf_formaddr(attr_list[i], &v_addr, &de) != DW_DLV_OK) { warnx("dwarf_formaddr failed: %s", dwarf_errmsg(de)); continue; } printf("%#jx", (uintmax_t) v_addr); break; case DW_FORM_data1: case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_udata: if (dwarf_formudata(attr_list[i], &v_udata, &de) != DW_DLV_OK) { warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); continue; } if (attr == DW_AT_high_pc) printf("0x%jx", (uintmax_t) v_udata); else printf("%ju", (uintmax_t) v_udata); break; case DW_FORM_sdata: if (dwarf_formsdata(attr_list[i], &v_sdata, &de) != DW_DLV_OK) { warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); continue; } printf("%jd", (intmax_t) v_sdata); break; case DW_FORM_flag: if (dwarf_formflag(attr_list[i], &v_bool, &de) != DW_DLV_OK) { warnx("dwarf_formflag failed: %s", dwarf_errmsg(de)); continue; } printf("%jd", (intmax_t) v_bool); break; case DW_FORM_flag_present: putchar('1'); break; case DW_FORM_string: case DW_FORM_strp: if (dwarf_formstring(attr_list[i], &v_str, &de) != DW_DLV_OK) { warnx("dwarf_formstring failed: %s", dwarf_errmsg(de)); continue; } if (form == DW_FORM_string) printf("%s", v_str); else printf("(indirect string) %s", v_str); break; case DW_FORM_block: case DW_FORM_block1: case DW_FORM_block2: case DW_FORM_block4: if (dwarf_formblock(attr_list[i], &v_block, &de) != DW_DLV_OK) { warnx("dwarf_formblock failed: %s", dwarf_errmsg(de)); continue; } printf("%ju byte block:", (uintmax_t) v_block->bl_len); b = v_block->bl_data; for (j = 0; (Dwarf_Unsigned) j < v_block->bl_len; j++) printf(" %x", b[j]); printf("\t("); dump_dwarf_block(re, v_block->bl_data, v_block->bl_len); putchar(')'); break; case DW_FORM_exprloc: if (dwarf_formexprloc(attr_list[i], &v_udata, &v_expr, &de) != DW_DLV_OK) { warnx("dwarf_formexprloc failed: %s", dwarf_errmsg(de)); continue; } printf("%ju byte block:", (uintmax_t) v_udata); b = v_expr; for (j = 0; (Dwarf_Unsigned) j < v_udata; j++) printf(" %x", b[j]); printf("\t("); dump_dwarf_block(re, v_expr, v_udata); putchar(')'); break; case DW_FORM_ref_sig8: if (dwarf_formsig8(attr_list[i], &v_sig8, &de) != DW_DLV_OK) { warnx("dwarf_formsig8 failed: %s", dwarf_errmsg(de)); continue; } p = (uint8_t *)(uintptr_t) &v_sig8.signature[0]; v_sig = re->dw_decode(&p, 8); printf("signature: 0x%jx", (uintmax_t) v_sig); } switch (attr) { case DW_AT_encoding: if (dwarf_attrval_unsigned(die, attr, &ate, &de) != DW_DLV_OK) break; if (dwarf_get_ATE_name(ate, &ate_str) != DW_DLV_OK) ate_str = "DW_ATE_UNKNOWN"; printf("\t(%s)", &ate_str[strlen("DW_ATE_")]); break; case DW_AT_language: if (dwarf_attrval_unsigned(die, attr, &lang, &de) != DW_DLV_OK) break; if (dwarf_get_LANG_name(lang, &lang_str) != DW_DLV_OK) break; printf("\t(%s)", &lang_str[strlen("DW_LANG_")]); break; case DW_AT_location: case DW_AT_string_length: case DW_AT_return_addr: case DW_AT_data_member_location: case DW_AT_frame_base: case DW_AT_segment: case DW_AT_static_link: case DW_AT_use_location: case DW_AT_vtable_elem_location: switch (form) { case DW_FORM_data4: case DW_FORM_data8: case DW_FORM_sec_offset: printf("\t(location list)"); break; default: break; } default: break; } putchar('\n'); } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) dump_dwarf_die(re, ret_die, level + 1); /* Search sibling. */ is_info = dwarf_get_die_infotypes_flag(die); ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) dump_dwarf_die(re, ret_die, level); dwarf_dealloc(re->dbg, die, DW_DLA_DIE); } static void set_cu_context(struct readelf *re, Dwarf_Half psize, Dwarf_Half osize, Dwarf_Half ver) { re->cu_psize = psize; re->cu_osize = osize; re->cu_ver = ver; } static void dump_dwarf_info(struct readelf *re, Dwarf_Bool is_info) { struct section *s; Dwarf_Die die; Dwarf_Error de; Dwarf_Half tag, version, pointer_size, off_size; Dwarf_Off cu_offset, cu_length; Dwarf_Off aboff; Dwarf_Unsigned typeoff; Dwarf_Sig8 sig8; Dwarf_Unsigned sig; uint8_t *p; const char *sn; int i, ret; sn = is_info ? ".debug_info" : ".debug_types"; s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && !strcmp(s->name, sn)) break; } if ((size_t) i >= re->shnum) return; do { printf("\nDump of debug contents of section %s:\n", sn); while ((ret = dwarf_next_cu_header_c(re->dbg, is_info, NULL, &version, &aboff, &pointer_size, &off_size, NULL, &sig8, &typeoff, NULL, &de)) == DW_DLV_OK) { set_cu_context(re, pointer_size, off_size, version); die = NULL; while (dwarf_siblingof_b(re->dbg, die, &die, is_info, &de) == DW_DLV_OK) { if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); continue; } /* XXX: What about DW_TAG_partial_unit? */ if ((is_info && tag == DW_TAG_compile_unit) || (!is_info && tag == DW_TAG_type_unit)) break; } if (die == NULL && is_info) { warnx("could not find DW_TAG_compile_unit " "die"); continue; } else if (die == NULL && !is_info) { warnx("could not find DW_TAG_type_unit die"); continue; } if (dwarf_die_CU_offset_range(die, &cu_offset, &cu_length, &de) != DW_DLV_OK) { warnx("dwarf_die_CU_offset failed: %s", dwarf_errmsg(de)); continue; } cu_length -= off_size == 4 ? 4 : 12; sig = 0; if (!is_info) { p = (uint8_t *)(uintptr_t) &sig8.signature[0]; sig = re->dw_decode(&p, 8); } printf("\n Type Unit @ offset 0x%jx:\n", (uintmax_t) cu_offset); printf(" Length:\t\t%#jx (%d-bit)\n", (uintmax_t) cu_length, off_size == 4 ? 32 : 64); printf(" Version:\t\t%u\n", version); printf(" Abbrev Offset:\t0x%jx\n", (uintmax_t) aboff); printf(" Pointer Size:\t%u\n", pointer_size); if (!is_info) { printf(" Signature:\t\t0x%016jx\n", (uintmax_t) sig); printf(" Type Offset:\t0x%jx\n", (uintmax_t) typeoff); } dump_dwarf_die(re, die, 0); } if (ret == DW_DLV_ERROR) warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); if (is_info) break; } while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK); } static void dump_dwarf_abbrev(struct readelf *re) { Dwarf_Abbrev ab; Dwarf_Off aboff, atoff; Dwarf_Unsigned length, attr_count; Dwarf_Signed flag, form; Dwarf_Half tag, attr; Dwarf_Error de; const char *tag_str, *attr_str, *form_str; char unk_tag[32], unk_attr[32], unk_form[32]; int i, j, ret; printf("\nContents of section .debug_abbrev:\n\n"); while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, &aboff, NULL, NULL, &de)) == DW_DLV_OK) { printf(" Number TAG\n"); i = 0; while ((ret = dwarf_get_abbrev(re->dbg, aboff, &ab, &length, &attr_count, &de)) == DW_DLV_OK) { if (length == 1) { dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV); break; } aboff += length; printf("%4d", ++i); if (dwarf_get_abbrev_tag(ab, &tag, &de) != DW_DLV_OK) { warnx("dwarf_get_abbrev_tag failed: %s", dwarf_errmsg(de)); goto next_abbrev; } if (dwarf_get_TAG_name(tag, &tag_str) != DW_DLV_OK) { snprintf(unk_tag, sizeof(unk_tag), "[Unknown Tag: %#x]", tag); tag_str = unk_tag; } if (dwarf_get_abbrev_children_flag(ab, &flag, &de) != DW_DLV_OK) { warnx("dwarf_get_abbrev_children_flag failed:" " %s", dwarf_errmsg(de)); goto next_abbrev; } printf(" %s %s\n", tag_str, flag ? "[has children]" : "[no children]"); for (j = 0; (Dwarf_Unsigned) j < attr_count; j++) { if (dwarf_get_abbrev_entry(ab, (Dwarf_Signed) j, &attr, &form, &atoff, &de) != DW_DLV_OK) { warnx("dwarf_get_abbrev_entry failed:" " %s", dwarf_errmsg(de)); continue; } if (dwarf_get_AT_name(attr, &attr_str) != DW_DLV_OK) { snprintf(unk_attr, sizeof(unk_attr), "[Unknown AT: %#x]", attr); attr_str = unk_attr; } if (dwarf_get_FORM_name(form, &form_str) != DW_DLV_OK) { snprintf(unk_form, sizeof(unk_form), "[Unknown Form: %#x]", (Dwarf_Half) form); form_str = unk_form; } printf(" %-18s %s\n", attr_str, form_str); } next_abbrev: dwarf_dealloc(re->dbg, ab, DW_DLA_ABBREV); } if (ret != DW_DLV_OK) warnx("dwarf_get_abbrev: %s", dwarf_errmsg(de)); } if (ret == DW_DLV_ERROR) warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); } static void dump_dwarf_pubnames(struct readelf *re) { struct section *s; Dwarf_Off die_off; Dwarf_Unsigned offset, length, nt_cu_offset, nt_cu_length; Dwarf_Signed cnt; Dwarf_Global *globs; Dwarf_Half nt_version; Dwarf_Error de; Elf_Data *d; char *glob_name; int i, dwarf_size, elferr; printf("\nContents of the .debug_pubnames section:\n"); s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && !strcmp(s->name, ".debug_pubnames")) break; } if ((size_t) i >= re->shnum) return; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_size <= 0) return; /* Read in .debug_pubnames section table header. */ offset = 0; length = re->dw_read(d, &offset, 4); if (length == 0xffffffff) { dwarf_size = 8; length = re->dw_read(d, &offset, 8); } else dwarf_size = 4; if (length > d->d_size - offset) { warnx("invalid .dwarf_pubnames section"); return; } nt_version = re->dw_read(d, &offset, 2); nt_cu_offset = re->dw_read(d, &offset, dwarf_size); nt_cu_length = re->dw_read(d, &offset, dwarf_size); printf(" Length:\t\t\t\t%ju\n", (uintmax_t) length); printf(" Version:\t\t\t\t%u\n", nt_version); printf(" Offset into .debug_info section:\t%ju\n", (uintmax_t) nt_cu_offset); printf(" Size of area in .debug_info section:\t%ju\n", (uintmax_t) nt_cu_length); if (dwarf_get_globals(re->dbg, &globs, &cnt, &de) != DW_DLV_OK) { warnx("dwarf_get_globals failed: %s", dwarf_errmsg(de)); return; } printf("\n Offset Name\n"); for (i = 0; i < cnt; i++) { if (dwarf_globname(globs[i], &glob_name, &de) != DW_DLV_OK) { warnx("dwarf_globname failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_global_die_offset(globs[i], &die_off, &de) != DW_DLV_OK) { warnx("dwarf_global_die_offset failed: %s", dwarf_errmsg(de)); continue; } printf(" %-11ju %s\n", (uintmax_t) die_off, glob_name); } } static void dump_dwarf_aranges(struct readelf *re) { struct section *s; Dwarf_Arange *aranges; Dwarf_Addr start; Dwarf_Unsigned offset, length, as_cu_offset; Dwarf_Off die_off; Dwarf_Signed cnt; Dwarf_Half as_version, as_addrsz, as_segsz; Dwarf_Error de; Elf_Data *d; int i, dwarf_size, elferr; printf("\nContents of section .debug_aranges:\n"); s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && !strcmp(s->name, ".debug_aranges")) break; } if ((size_t) i >= re->shnum) return; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_size <= 0) return; /* Read in the .debug_aranges section table header. */ offset = 0; length = re->dw_read(d, &offset, 4); if (length == 0xffffffff) { dwarf_size = 8; length = re->dw_read(d, &offset, 8); } else dwarf_size = 4; if (length > d->d_size - offset) { warnx("invalid .dwarf_aranges section"); return; } as_version = re->dw_read(d, &offset, 2); as_cu_offset = re->dw_read(d, &offset, dwarf_size); as_addrsz = re->dw_read(d, &offset, 1); as_segsz = re->dw_read(d, &offset, 1); printf(" Length:\t\t\t%ju\n", (uintmax_t) length); printf(" Version:\t\t\t%u\n", as_version); printf(" Offset into .debug_info:\t%ju\n", (uintmax_t) as_cu_offset); printf(" Pointer Size:\t\t\t%u\n", as_addrsz); printf(" Segment Size:\t\t\t%u\n", as_segsz); if (dwarf_get_aranges(re->dbg, &aranges, &cnt, &de) != DW_DLV_OK) { warnx("dwarf_get_aranges failed: %s", dwarf_errmsg(de)); return; } printf("\n Address Length\n"); for (i = 0; i < cnt; i++) { if (dwarf_get_arange_info(aranges[i], &start, &length, &die_off, &de) != DW_DLV_OK) { warnx("dwarf_get_arange_info failed: %s", dwarf_errmsg(de)); continue; } printf(" %08jx %ju\n", (uintmax_t) start, (uintmax_t) length); } } static void dump_dwarf_ranges_foreach(struct readelf *re, Dwarf_Die die, Dwarf_Addr base) { Dwarf_Attribute *attr_list; Dwarf_Ranges *ranges; Dwarf_Die ret_die; Dwarf_Error de; Dwarf_Addr base0; Dwarf_Half attr; Dwarf_Signed attr_count, cnt; Dwarf_Unsigned off, bytecnt; int i, j, ret; if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != DW_DLV_OK) { if (ret == DW_DLV_ERROR) warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); goto cont_search; } for (i = 0; i < attr_count; i++) { if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); continue; } if (attr != DW_AT_ranges) continue; if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) { warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_get_ranges(re->dbg, (Dwarf_Off) off, &ranges, &cnt, &bytecnt, &de) != DW_DLV_OK) continue; base0 = base; for (j = 0; j < cnt; j++) { printf(" %08jx ", (uintmax_t) off); if (ranges[j].dwr_type == DW_RANGES_END) { printf("%s\n", ""); continue; } else if (ranges[j].dwr_type == DW_RANGES_ADDRESS_SELECTION) { base0 = ranges[j].dwr_addr2; continue; } if (re->ec == ELFCLASS32) printf("%08jx %08jx\n", ranges[j].dwr_addr1 + base0, ranges[j].dwr_addr2 + base0); else printf("%016jx %016jx\n", ranges[j].dwr_addr1 + base0, ranges[j].dwr_addr2 + base0); } } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) dump_dwarf_ranges_foreach(re, ret_die, base); /* Search sibling. */ ret = dwarf_siblingof(re->dbg, die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) dump_dwarf_ranges_foreach(re, ret_die, base); } static void dump_dwarf_ranges(struct readelf *re) { Dwarf_Ranges *ranges; Dwarf_Die die; Dwarf_Signed cnt; Dwarf_Unsigned bytecnt; Dwarf_Half tag; Dwarf_Error de; Dwarf_Unsigned lowpc; int ret; if (dwarf_get_ranges(re->dbg, 0, &ranges, &cnt, &bytecnt, &de) != DW_DLV_OK) return; printf("Contents of the .debug_ranges section:\n\n"); if (re->ec == ELFCLASS32) printf(" %-8s %-8s %s\n", "Offset", "Begin", "End"); else printf(" %-8s %-16s %s\n", "Offset", "Begin", "End"); while ((ret = dwarf_next_cu_header(re->dbg, NULL, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { die = NULL; if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK) continue; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); continue; } /* XXX: What about DW_TAG_partial_unit? */ lowpc = 0; if (tag == DW_TAG_compile_unit) { if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc, &de) != DW_DLV_OK) lowpc = 0; } dump_dwarf_ranges_foreach(re, die, (Dwarf_Addr) lowpc); } putchar('\n'); } static void dump_dwarf_macinfo(struct readelf *re) { Dwarf_Unsigned offset; Dwarf_Signed cnt; Dwarf_Macro_Details *md; Dwarf_Error de; const char *mi_str; char unk_mi[32]; int i; #define _MAX_MACINFO_ENTRY 65535 printf("\nContents of section .debug_macinfo:\n\n"); offset = 0; while (dwarf_get_macro_details(re->dbg, offset, _MAX_MACINFO_ENTRY, &cnt, &md, &de) == DW_DLV_OK) { for (i = 0; i < cnt; i++) { offset = md[i].dmd_offset + 1; if (md[i].dmd_type == 0) break; if (dwarf_get_MACINFO_name(md[i].dmd_type, &mi_str) != DW_DLV_OK) { snprintf(unk_mi, sizeof(unk_mi), "[Unknown MACINFO: %#x]", md[i].dmd_type); mi_str = unk_mi; } printf(" %s", mi_str); switch (md[i].dmd_type) { case DW_MACINFO_define: case DW_MACINFO_undef: printf(" - lineno : %jd macro : %s\n", (intmax_t) md[i].dmd_lineno, md[i].dmd_macro); break; case DW_MACINFO_start_file: printf(" - lineno : %jd filenum : %jd\n", (intmax_t) md[i].dmd_lineno, (intmax_t) md[i].dmd_fileindex); break; default: putchar('\n'); break; } } } #undef _MAX_MACINFO_ENTRY } static void dump_dwarf_frame_inst(struct readelf *re, Dwarf_Cie cie, uint8_t *insts, Dwarf_Unsigned len, Dwarf_Unsigned caf, Dwarf_Signed daf, Dwarf_Addr pc, Dwarf_Debug dbg) { Dwarf_Frame_Op *oplist; Dwarf_Signed opcnt, delta; Dwarf_Small op; Dwarf_Error de; const char *op_str; char unk_op[32]; int i; if (dwarf_expand_frame_instructions(cie, insts, len, &oplist, &opcnt, &de) != DW_DLV_OK) { warnx("dwarf_expand_frame_instructions failed: %s", dwarf_errmsg(de)); return; } for (i = 0; i < opcnt; i++) { if (oplist[i].fp_base_op != 0) op = oplist[i].fp_base_op << 6; else op = oplist[i].fp_extended_op; if (dwarf_get_CFA_name(op, &op_str) != DW_DLV_OK) { snprintf(unk_op, sizeof(unk_op), "[Unknown CFA: %#x]", op); op_str = unk_op; } printf(" %s", op_str); switch (op) { case DW_CFA_advance_loc: delta = oplist[i].fp_offset * caf; pc += delta; printf(": %ju to %08jx", (uintmax_t) delta, (uintmax_t) pc); break; case DW_CFA_offset: case DW_CFA_offset_extended: case DW_CFA_offset_extended_sf: delta = oplist[i].fp_offset * daf; printf(": r%u (%s) at cfa%+jd", oplist[i].fp_register, dwarf_regname(re, oplist[i].fp_register), (intmax_t) delta); break; case DW_CFA_restore: printf(": r%u (%s)", oplist[i].fp_register, dwarf_regname(re, oplist[i].fp_register)); break; case DW_CFA_set_loc: pc = oplist[i].fp_offset; printf(": to %08jx", (uintmax_t) pc); break; case DW_CFA_advance_loc1: case DW_CFA_advance_loc2: case DW_CFA_advance_loc4: pc += oplist[i].fp_offset; printf(": %jd to %08jx", (intmax_t) oplist[i].fp_offset, (uintmax_t) pc); break; case DW_CFA_def_cfa: printf(": r%u (%s) ofs %ju", oplist[i].fp_register, dwarf_regname(re, oplist[i].fp_register), (uintmax_t) oplist[i].fp_offset); break; case DW_CFA_def_cfa_sf: printf(": r%u (%s) ofs %jd", oplist[i].fp_register, dwarf_regname(re, oplist[i].fp_register), (intmax_t) (oplist[i].fp_offset * daf)); break; case DW_CFA_def_cfa_register: printf(": r%u (%s)", oplist[i].fp_register, dwarf_regname(re, oplist[i].fp_register)); break; case DW_CFA_def_cfa_offset: printf(": %ju", (uintmax_t) oplist[i].fp_offset); break; case DW_CFA_def_cfa_offset_sf: printf(": %jd", (intmax_t) (oplist[i].fp_offset * daf)); break; default: break; } putchar('\n'); } dwarf_dealloc(dbg, oplist, DW_DLA_FRAME_BLOCK); } static char * get_regoff_str(struct readelf *re, Dwarf_Half reg, Dwarf_Addr off) { static char rs[16]; if (reg == DW_FRAME_UNDEFINED_VAL || reg == DW_FRAME_REG_INITIAL_VALUE) snprintf(rs, sizeof(rs), "%c", 'u'); else if (reg == DW_FRAME_CFA_COL) snprintf(rs, sizeof(rs), "c%+jd", (intmax_t) off); else snprintf(rs, sizeof(rs), "%s%+jd", dwarf_regname(re, reg), (intmax_t) off); return (rs); } static int dump_dwarf_frame_regtable(struct readelf *re, Dwarf_Fde fde, Dwarf_Addr pc, Dwarf_Unsigned func_len, Dwarf_Half cie_ra) { Dwarf_Regtable rt; Dwarf_Addr row_pc, end_pc, pre_pc, cur_pc; Dwarf_Error de; char *vec; int i; #define BIT_SET(v, n) (v[(n)>>3] |= 1U << ((n) & 7)) #define BIT_CLR(v, n) (v[(n)>>3] &= ~(1U << ((n) & 7))) #define BIT_ISSET(v, n) (v[(n)>>3] & (1U << ((n) & 7))) #define RT(x) rt.rules[(x)] vec = calloc((DW_REG_TABLE_SIZE + 7) / 8, 1); if (vec == NULL) err(EXIT_FAILURE, "calloc failed"); pre_pc = ~((Dwarf_Addr) 0); cur_pc = pc; end_pc = pc + func_len; for (; cur_pc < end_pc; cur_pc++) { if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_info_for_all_regs failed: %s\n", dwarf_errmsg(de)); return (-1); } if (row_pc == pre_pc) continue; pre_pc = row_pc; for (i = 1; i < DW_REG_TABLE_SIZE; i++) { if (rt.rules[i].dw_regnum != DW_FRAME_REG_INITIAL_VALUE) BIT_SET(vec, i); } } printf(" LOC CFA "); for (i = 1; i < DW_REG_TABLE_SIZE; i++) { if (BIT_ISSET(vec, i)) { if ((Dwarf_Half) i == cie_ra) printf("ra "); else printf("%-5s", dwarf_regname(re, (unsigned int) i)); } } putchar('\n'); pre_pc = ~((Dwarf_Addr) 0); cur_pc = pc; end_pc = pc + func_len; for (; cur_pc < end_pc; cur_pc++) { if (dwarf_get_fde_info_for_all_regs(fde, cur_pc, &rt, &row_pc, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_info_for_all_regs failed: %s\n", dwarf_errmsg(de)); return (-1); } if (row_pc == pre_pc) continue; pre_pc = row_pc; printf("%08jx ", (uintmax_t) row_pc); printf("%-8s ", get_regoff_str(re, RT(0).dw_regnum, RT(0).dw_offset)); for (i = 1; i < DW_REG_TABLE_SIZE; i++) { if (BIT_ISSET(vec, i)) { printf("%-5s", get_regoff_str(re, RT(i).dw_regnum, RT(i).dw_offset)); } } putchar('\n'); } free(vec); return (0); #undef BIT_SET #undef BIT_CLR #undef BIT_ISSET #undef RT } static void dump_dwarf_frame_section(struct readelf *re, struct section *s, int alt) { Dwarf_Cie *cie_list, cie, pre_cie; Dwarf_Fde *fde_list, fde; Dwarf_Off cie_offset, fde_offset; Dwarf_Unsigned cie_length, fde_instlen; Dwarf_Unsigned cie_caf, cie_daf, cie_instlen, func_len, fde_length; Dwarf_Signed cie_count, fde_count, cie_index; Dwarf_Addr low_pc; Dwarf_Half cie_ra; Dwarf_Small cie_version; Dwarf_Ptr fde_addr, fde_inst, cie_inst; char *cie_aug, c; int i, eh_frame; Dwarf_Error de; printf("\nThe section %s contains:\n\n", s->name); if (!strcmp(s->name, ".debug_frame")) { eh_frame = 0; if (dwarf_get_fde_list(re->dbg, &cie_list, &cie_count, &fde_list, &fde_count, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_list failed: %s", dwarf_errmsg(de)); return; } } else if (!strcmp(s->name, ".eh_frame")) { eh_frame = 1; if (dwarf_get_fde_list_eh(re->dbg, &cie_list, &cie_count, &fde_list, &fde_count, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_list_eh failed: %s", dwarf_errmsg(de)); return; } } else return; pre_cie = NULL; for (i = 0; i < fde_count; i++) { if (dwarf_get_fde_n(fde_list, i, &fde, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_get_cie_of_fde(fde, &cie, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_n failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_get_fde_range(fde, &low_pc, &func_len, &fde_addr, &fde_length, &cie_offset, &cie_index, &fde_offset, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_range failed: %s", dwarf_errmsg(de)); continue; } if (dwarf_get_fde_instr_bytes(fde, &fde_inst, &fde_instlen, &de) != DW_DLV_OK) { warnx("dwarf_get_fde_instr_bytes failed: %s", dwarf_errmsg(de)); continue; } if (pre_cie == NULL || cie != pre_cie) { pre_cie = cie; if (dwarf_get_cie_info(cie, &cie_length, &cie_version, &cie_aug, &cie_caf, &cie_daf, &cie_ra, &cie_inst, &cie_instlen, &de) != DW_DLV_OK) { warnx("dwarf_get_cie_info failed: %s", dwarf_errmsg(de)); continue; } printf("%08jx %08jx %8.8jx CIE", (uintmax_t) cie_offset, (uintmax_t) cie_length, (uintmax_t) (eh_frame ? 0 : ~0U)); if (!alt) { putchar('\n'); printf(" Version:\t\t\t%u\n", cie_version); printf(" Augmentation:\t\t\t\""); while ((c = *cie_aug++) != '\0') putchar(c); printf("\"\n"); printf(" Code alignment factor:\t%ju\n", (uintmax_t) cie_caf); printf(" Data alignment factor:\t%jd\n", (intmax_t) cie_daf); printf(" Return address column:\t%ju\n", (uintmax_t) cie_ra); putchar('\n'); dump_dwarf_frame_inst(re, cie, cie_inst, cie_instlen, cie_caf, cie_daf, 0, re->dbg); putchar('\n'); } else { printf(" \""); while ((c = *cie_aug++) != '\0') putchar(c); putchar('"'); printf(" cf=%ju df=%jd ra=%ju\n", (uintmax_t) cie_caf, (uintmax_t) cie_daf, (uintmax_t) cie_ra); dump_dwarf_frame_regtable(re, fde, low_pc, 1, cie_ra); putchar('\n'); } } printf("%08jx %08jx %08jx FDE cie=%08jx pc=%08jx..%08jx\n", (uintmax_t) fde_offset, (uintmax_t) fde_length, (uintmax_t) cie_offset, (uintmax_t) (eh_frame ? fde_offset + 4 - cie_offset : cie_offset), (uintmax_t) low_pc, (uintmax_t) (low_pc + func_len)); if (!alt) dump_dwarf_frame_inst(re, cie, fde_inst, fde_instlen, cie_caf, cie_daf, low_pc, re->dbg); else dump_dwarf_frame_regtable(re, fde, low_pc, func_len, cie_ra); putchar('\n'); } } static void dump_dwarf_frame(struct readelf *re, int alt) { struct section *s; int i; (void) dwarf_set_frame_cfa_value(re->dbg, DW_FRAME_CFA_COL); for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && (!strcmp(s->name, ".debug_frame") || !strcmp(s->name, ".eh_frame"))) dump_dwarf_frame_section(re, s, alt); } } static void dump_dwarf_str(struct readelf *re) { struct section *s; Elf_Data *d; unsigned char *p; int elferr, end, i, j; printf("\nContents of section .debug_str:\n"); s = NULL; for (i = 0; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (s->name != NULL && !strcmp(s->name, ".debug_str")) break; } if ((size_t) i >= re->shnum) return; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(-1)); return; } if (d->d_size <= 0) return; for (i = 0, p = d->d_buf; (size_t) i < d->d_size; i += 16) { printf(" 0x%08x", (unsigned int) i); if ((size_t) i + 16 > d->d_size) end = d->d_size; else end = i + 16; for (j = i; j < i + 16; j++) { if ((j - i) % 4 == 0) putchar(' '); if (j >= end) { printf(" "); continue; } printf("%02x", (uint8_t) p[j]); } putchar(' '); for (j = i; j < end; j++) { if (isprint(p[j])) putchar(p[j]); else if (p[j] == 0) putchar('.'); else putchar(' '); } putchar('\n'); } } struct loc_at { Dwarf_Attribute la_at; Dwarf_Unsigned la_off; Dwarf_Unsigned la_lowpc; Dwarf_Half la_cu_psize; Dwarf_Half la_cu_osize; Dwarf_Half la_cu_ver; TAILQ_ENTRY(loc_at) la_next; }; static TAILQ_HEAD(, loc_at) lalist = TAILQ_HEAD_INITIALIZER(lalist); static void search_loclist_at(struct readelf *re, Dwarf_Die die, Dwarf_Unsigned lowpc) { Dwarf_Attribute *attr_list; Dwarf_Die ret_die; Dwarf_Unsigned off; Dwarf_Off ref; Dwarf_Signed attr_count; Dwarf_Half attr, form; Dwarf_Bool is_info; Dwarf_Error de; struct loc_at *la, *nla; int i, ret; is_info = dwarf_get_die_infotypes_flag(die); if ((ret = dwarf_attrlist(die, &attr_list, &attr_count, &de)) != DW_DLV_OK) { if (ret == DW_DLV_ERROR) warnx("dwarf_attrlist failed: %s", dwarf_errmsg(de)); goto cont_search; } for (i = 0; i < attr_count; i++) { if (dwarf_whatattr(attr_list[i], &attr, &de) != DW_DLV_OK) { warnx("dwarf_whatattr failed: %s", dwarf_errmsg(de)); continue; } if (attr != DW_AT_location && attr != DW_AT_string_length && attr != DW_AT_return_addr && attr != DW_AT_data_member_location && attr != DW_AT_frame_base && attr != DW_AT_segment && attr != DW_AT_static_link && attr != DW_AT_use_location && attr != DW_AT_vtable_elem_location) continue; if (dwarf_whatform(attr_list[i], &form, &de) != DW_DLV_OK) { warnx("dwarf_whatform failed: %s", dwarf_errmsg(de)); continue; } if (form == DW_FORM_data4 || form == DW_FORM_data8) { if (dwarf_formudata(attr_list[i], &off, &de) != DW_DLV_OK) { warnx("dwarf_formudata failed: %s", dwarf_errmsg(de)); continue; } } else if (form == DW_FORM_sec_offset) { if (dwarf_global_formref(attr_list[i], &ref, &de) != DW_DLV_OK) { warnx("dwarf_global_formref failed: %s", dwarf_errmsg(de)); continue; } off = ref; } else continue; TAILQ_FOREACH(la, &lalist, la_next) { if (off == la->la_off) break; if (off < la->la_off) { if ((nla = malloc(sizeof(*nla))) == NULL) err(EXIT_FAILURE, "malloc failed"); nla->la_at = attr_list[i]; nla->la_off = off; nla->la_lowpc = lowpc; nla->la_cu_psize = re->cu_psize; nla->la_cu_osize = re->cu_osize; nla->la_cu_ver = re->cu_ver; TAILQ_INSERT_BEFORE(la, nla, la_next); break; } } if (la == NULL) { if ((nla = malloc(sizeof(*nla))) == NULL) err(EXIT_FAILURE, "malloc failed"); nla->la_at = attr_list[i]; nla->la_off = off; nla->la_lowpc = lowpc; nla->la_cu_psize = re->cu_psize; nla->la_cu_osize = re->cu_osize; nla->la_cu_ver = re->cu_ver; TAILQ_INSERT_TAIL(&lalist, nla, la_next); } } cont_search: /* Search children. */ ret = dwarf_child(die, &ret_die, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_child: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_loclist_at(re, ret_die, lowpc); /* Search sibling. */ ret = dwarf_siblingof_b(re->dbg, die, &ret_die, is_info, &de); if (ret == DW_DLV_ERROR) warnx("dwarf_siblingof: %s", dwarf_errmsg(de)); else if (ret == DW_DLV_OK) search_loclist_at(re, ret_die, lowpc); } static void dump_dwarf_loc(struct readelf *re, Dwarf_Loc *lr) { const char *op_str; char unk_op[32]; uint8_t *b, n; int i; if (dwarf_get_OP_name(lr->lr_atom, &op_str) != DW_DLV_OK) { snprintf(unk_op, sizeof(unk_op), "[Unknown OP: %#x]", lr->lr_atom); op_str = unk_op; } printf("%s", op_str); switch (lr->lr_atom) { case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3: case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7: case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11: case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15: case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19: case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23: case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27: case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31: printf(" (%s)", dwarf_regname(re, lr->lr_atom - DW_OP_reg0)); break; case DW_OP_deref: case DW_OP_lit0: case DW_OP_lit1: case DW_OP_lit2: case DW_OP_lit3: case DW_OP_lit4: case DW_OP_lit5: case DW_OP_lit6: case DW_OP_lit7: case DW_OP_lit8: case DW_OP_lit9: case DW_OP_lit10: case DW_OP_lit11: case DW_OP_lit12: case DW_OP_lit13: case DW_OP_lit14: case DW_OP_lit15: case DW_OP_lit16: case DW_OP_lit17: case DW_OP_lit18: case DW_OP_lit19: case DW_OP_lit20: case DW_OP_lit21: case DW_OP_lit22: case DW_OP_lit23: case DW_OP_lit24: case DW_OP_lit25: case DW_OP_lit26: case DW_OP_lit27: case DW_OP_lit28: case DW_OP_lit29: case DW_OP_lit30: case DW_OP_lit31: case DW_OP_dup: case DW_OP_drop: case DW_OP_over: case DW_OP_swap: case DW_OP_rot: case DW_OP_xderef: case DW_OP_abs: case DW_OP_and: case DW_OP_div: case DW_OP_minus: case DW_OP_mod: case DW_OP_mul: case DW_OP_neg: case DW_OP_not: case DW_OP_or: case DW_OP_plus: case DW_OP_shl: case DW_OP_shr: case DW_OP_shra: case DW_OP_xor: case DW_OP_eq: case DW_OP_ge: case DW_OP_gt: case DW_OP_le: case DW_OP_lt: case DW_OP_ne: case DW_OP_nop: case DW_OP_push_object_address: case DW_OP_form_tls_address: case DW_OP_call_frame_cfa: case DW_OP_stack_value: case DW_OP_GNU_push_tls_address: case DW_OP_GNU_uninit: break; case DW_OP_const1u: case DW_OP_pick: case DW_OP_deref_size: case DW_OP_xderef_size: case DW_OP_const2u: case DW_OP_bra: case DW_OP_skip: case DW_OP_const4u: case DW_OP_const8u: case DW_OP_constu: case DW_OP_plus_uconst: case DW_OP_regx: case DW_OP_piece: printf(": %ju", (uintmax_t) lr->lr_number); break; case DW_OP_const1s: case DW_OP_const2s: case DW_OP_const4s: case DW_OP_const8s: case DW_OP_consts: printf(": %jd", (intmax_t) lr->lr_number); break; case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: printf(" (%s): %jd", dwarf_regname(re, lr->lr_atom - DW_OP_breg0), (intmax_t) lr->lr_number); break; case DW_OP_fbreg: printf(": %jd", (intmax_t) lr->lr_number); break; case DW_OP_bregx: printf(": %ju (%s) %jd", (uintmax_t) lr->lr_number, dwarf_regname(re, (unsigned int) lr->lr_number), (intmax_t) lr->lr_number2); break; case DW_OP_addr: case DW_OP_GNU_encoded_addr: printf(": %#jx", (uintmax_t) lr->lr_number); break; case DW_OP_GNU_implicit_pointer: printf(": <0x%jx> %jd", (uintmax_t) lr->lr_number, (intmax_t) lr->lr_number2); break; case DW_OP_implicit_value: printf(": %ju byte block:", (uintmax_t) lr->lr_number); b = (uint8_t *)(uintptr_t) lr->lr_number2; for (i = 0; (Dwarf_Unsigned) i < lr->lr_number; i++) printf(" %x", b[i]); break; case DW_OP_GNU_entry_value: printf(": ("); dump_dwarf_block(re, (uint8_t *)(uintptr_t) lr->lr_number2, lr->lr_number); putchar(')'); break; case DW_OP_GNU_const_type: printf(": <0x%jx> ", (uintmax_t) lr->lr_number); b = (uint8_t *)(uintptr_t) lr->lr_number2; n = *b; for (i = 1; (uint8_t) i < n; i++) printf(" %x", b[i]); break; case DW_OP_GNU_regval_type: printf(": %ju (%s) <0x%jx>", (uintmax_t) lr->lr_number, dwarf_regname(re, (unsigned int) lr->lr_number), (uintmax_t) lr->lr_number2); break; case DW_OP_GNU_convert: case DW_OP_GNU_deref_type: case DW_OP_GNU_parameter_ref: case DW_OP_GNU_reinterpret: printf(": <0x%jx>", (uintmax_t) lr->lr_number); break; default: break; } } static void dump_dwarf_block(struct readelf *re, uint8_t *b, Dwarf_Unsigned len) { Dwarf_Locdesc *llbuf; Dwarf_Signed lcnt; Dwarf_Error de; int i; if (dwarf_loclist_from_expr_b(re->dbg, b, len, re->cu_psize, re->cu_osize, re->cu_ver, &llbuf, &lcnt, &de) != DW_DLV_OK) { warnx("dwarf_loclist_form_expr_b: %s", dwarf_errmsg(de)); return; } for (i = 0; (Dwarf_Half) i < llbuf->ld_cents; i++) { dump_dwarf_loc(re, &llbuf->ld_s[i]); if (i < llbuf->ld_cents - 1) printf("; "); } dwarf_dealloc(re->dbg, llbuf->ld_s, DW_DLA_LOC_BLOCK); dwarf_dealloc(re->dbg, llbuf, DW_DLA_LOCDESC); } static void dump_dwarf_loclist(struct readelf *re) { Dwarf_Die die; Dwarf_Locdesc **llbuf; Dwarf_Unsigned lowpc; Dwarf_Signed lcnt; Dwarf_Half tag, version, pointer_size, off_size; Dwarf_Error de; struct loc_at *la; int i, j, ret; printf("\nContents of section .debug_loc:\n"); /* Search .debug_info section. */ while ((ret = dwarf_next_cu_header_b(re->dbg, NULL, &version, NULL, &pointer_size, &off_size, NULL, NULL, &de)) == DW_DLV_OK) { set_cu_context(re, pointer_size, off_size, version); die = NULL; if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK) continue; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); continue; } /* XXX: What about DW_TAG_partial_unit? */ lowpc = 0; if (tag == DW_TAG_compile_unit) { if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc, &de) != DW_DLV_OK) lowpc = 0; } /* Search attributes for reference to .debug_loc section. */ search_loclist_at(re, die, lowpc); } if (ret == DW_DLV_ERROR) warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); /* Search .debug_types section. */ do { while ((ret = dwarf_next_cu_header_c(re->dbg, 0, NULL, &version, NULL, &pointer_size, &off_size, NULL, NULL, NULL, NULL, &de)) == DW_DLV_OK) { set_cu_context(re, pointer_size, off_size, version); die = NULL; if (dwarf_siblingof(re->dbg, die, &die, &de) != DW_DLV_OK) continue; if (dwarf_tag(die, &tag, &de) != DW_DLV_OK) { warnx("dwarf_tag failed: %s", dwarf_errmsg(de)); continue; } lowpc = 0; if (tag == DW_TAG_type_unit) { if (dwarf_attrval_unsigned(die, DW_AT_low_pc, &lowpc, &de) != DW_DLV_OK) lowpc = 0; } /* * Search attributes for reference to .debug_loc * section. */ search_loclist_at(re, die, lowpc); } if (ret == DW_DLV_ERROR) warnx("dwarf_next_cu_header: %s", dwarf_errmsg(de)); } while (dwarf_next_types_section(re->dbg, &de) == DW_DLV_OK); if (TAILQ_EMPTY(&lalist)) return; printf(" Offset Begin End Expression\n"); TAILQ_FOREACH(la, &lalist, la_next) { if (dwarf_loclist_n(la->la_at, &llbuf, &lcnt, &de) != DW_DLV_OK) { warnx("dwarf_loclist_n failed: %s", dwarf_errmsg(de)); continue; } set_cu_context(re, la->la_cu_psize, la->la_cu_osize, la->la_cu_ver); for (i = 0; i < lcnt; i++) { printf(" %8.8jx ", la->la_off); if (llbuf[i]->ld_lopc == 0 && llbuf[i]->ld_hipc == 0) { printf("\n"); continue; } /* TODO: handle base selection entry. */ printf("%8.8jx %8.8jx ", (uintmax_t) (la->la_lowpc + llbuf[i]->ld_lopc), (uintmax_t) (la->la_lowpc + llbuf[i]->ld_hipc)); putchar('('); for (j = 0; (Dwarf_Half) j < llbuf[i]->ld_cents; j++) { dump_dwarf_loc(re, &llbuf[i]->ld_s[j]); if (j < llbuf[i]->ld_cents - 1) printf("; "); } putchar(')'); if (llbuf[i]->ld_lopc == llbuf[i]->ld_hipc) printf(" (start == end)"); putchar('\n'); } for (i = 0; i < lcnt; i++) { dwarf_dealloc(re->dbg, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); dwarf_dealloc(re->dbg, llbuf[i], DW_DLA_LOCDESC); } dwarf_dealloc(re->dbg, llbuf, DW_DLA_LIST); } } /* * Retrieve a string using string table section index and the string offset. */ static const char* get_string(struct readelf *re, int strtab, size_t off) { const char *name; if ((name = elf_strptr(re->elf, strtab, off)) == NULL) return (""); return (name); } /* * Retrieve the name of a symbol using the section index of the symbol * table and the index of the symbol within that table. */ static const char * get_symbol_name(struct readelf *re, int symtab, int i) { struct section *s; const char *name; GElf_Sym sym; Elf_Data *data; int elferr; s = &re->sl[symtab]; if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) return (""); (void) elf_errno(); if ((data = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return (""); } if (gelf_getsym(data, i, &sym) != &sym) return (""); /* Return section name for STT_SECTION symbol. */ if (GELF_ST_TYPE(sym.st_info) == STT_SECTION && re->sl[sym.st_shndx].name != NULL) return (re->sl[sym.st_shndx].name); if ((name = elf_strptr(re->elf, s->link, sym.st_name)) == NULL) return (""); return (name); } static uint64_t get_symbol_value(struct readelf *re, int symtab, int i) { struct section *s; GElf_Sym sym; Elf_Data *data; int elferr; s = &re->sl[symtab]; if (s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) return (0); (void) elf_errno(); if ((data = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); return (0); } if (gelf_getsym(data, i, &sym) != &sym) return (0); return (sym.st_value); } static void hex_dump(struct readelf *re) { struct section *s; Elf_Data *d; uint8_t *buf; size_t sz, nbytes; uint64_t addr; int elferr, i, j; for (i = 1; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (find_dumpop(re, (size_t) i, s->name, HEX_DUMP, -1) == NULL) continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } if (d->d_size <= 0 || d->d_buf == NULL) { printf("\nSection '%s' has no data to dump.\n", s->name); continue; } buf = d->d_buf; sz = d->d_size; addr = s->addr; printf("\nHex dump of section '%s':\n", s->name); while (sz > 0) { printf(" 0x%8.8jx ", (uintmax_t)addr); nbytes = sz > 16? 16 : sz; for (j = 0; j < 16; j++) { if ((size_t)j < nbytes) printf("%2.2x", buf[j]); else printf(" "); if ((j & 3) == 3) printf(" "); } for (j = 0; (size_t)j < nbytes; j++) { if (isprint(buf[j])) printf("%c", buf[j]); else printf("."); } printf("\n"); buf += nbytes; addr += nbytes; sz -= nbytes; } } } static void str_dump(struct readelf *re) { struct section *s; Elf_Data *d; unsigned char *start, *end, *buf_end; unsigned int len; int i, j, elferr, found; for (i = 1; (size_t) i < re->shnum; i++) { s = &re->sl[i]; if (find_dumpop(re, (size_t) i, s->name, STR_DUMP, -1) == NULL) continue; (void) elf_errno(); if ((d = elf_getdata(s->scn, NULL)) == NULL) { elferr = elf_errno(); if (elferr != 0) warnx("elf_getdata failed: %s", elf_errmsg(elferr)); continue; } if (d->d_size <= 0 || d->d_buf == NULL) { printf("\nSection '%s' has no data to dump.\n", s->name); continue; } buf_end = (unsigned char *) d->d_buf + d->d_size; start = (unsigned char *) d->d_buf; found = 0; printf("\nString dump of section '%s':\n", s->name); for (;;) { while (start < buf_end && !isprint(*start)) start++; if (start >= buf_end) break; end = start + 1; while (end < buf_end && isprint(*end)) end++; printf(" [%6lx] ", (long) (start - (unsigned char *) d->d_buf)); len = end - start; for (j = 0; (unsigned int) j < len; j++) putchar(start[j]); putchar('\n'); found = 1; if (end >= buf_end) break; start = end + 1; } if (!found) printf(" No strings found in this section."); putchar('\n'); } } static void load_sections(struct readelf *re) { struct section *s; const char *name; Elf_Scn *scn; GElf_Shdr sh; size_t shstrndx, ndx; int elferr; /* Allocate storage for internal section list. */ if (!elf_getshnum(re->elf, &re->shnum)) { warnx("elf_getshnum failed: %s", elf_errmsg(-1)); return; } if (re->sl != NULL) free(re->sl); if ((re->sl = calloc(re->shnum, sizeof(*re->sl))) == NULL) err(EXIT_FAILURE, "calloc failed"); /* Get the index of .shstrtab section. */ if (!elf_getshstrndx(re->elf, &shstrndx)) { warnx("elf_getshstrndx failed: %s", elf_errmsg(-1)); return; } if ((scn = elf_getscn(re->elf, 0)) == NULL) return; (void) elf_errno(); do { if (gelf_getshdr(scn, &sh) == NULL) { warnx("gelf_getshdr failed: %s", elf_errmsg(-1)); (void) elf_errno(); continue; } if ((name = elf_strptr(re->elf, shstrndx, sh.sh_name)) == NULL) { (void) elf_errno(); name = "ERROR"; } if ((ndx = elf_ndxscn(scn)) == SHN_UNDEF) { if ((elferr = elf_errno()) != 0) warnx("elf_ndxscn failed: %s", elf_errmsg(elferr)); continue; } if (ndx >= re->shnum) { warnx("section index of '%s' out of range", name); continue; } s = &re->sl[ndx]; s->name = name; s->scn = scn; s->off = sh.sh_offset; s->sz = sh.sh_size; s->entsize = sh.sh_entsize; s->align = sh.sh_addralign; s->type = sh.sh_type; s->flags = sh.sh_flags; s->addr = sh.sh_addr; s->link = sh.sh_link; s->info = sh.sh_info; } while ((scn = elf_nextscn(re->elf, scn)) != NULL); elferr = elf_errno(); if (elferr != 0) warnx("elf_nextscn failed: %s", elf_errmsg(elferr)); } static void unload_sections(struct readelf *re) { if (re->sl != NULL) { free(re->sl); re->sl = NULL; } re->shnum = 0; re->vd_s = NULL; re->vn_s = NULL; re->vs_s = NULL; re->vs = NULL; re->vs_sz = 0; if (re->ver != NULL) { free(re->ver); re->ver = NULL; re->ver_sz = 0; } } static void dump_elf(struct readelf *re) { /* Fetch ELF header. No need to continue if it fails. */ if (gelf_getehdr(re->elf, &re->ehdr) == NULL) { warnx("gelf_getehdr failed: %s", elf_errmsg(-1)); return; } if ((re->ec = gelf_getclass(re->elf)) == ELFCLASSNONE) { warnx("gelf_getclass failed: %s", elf_errmsg(-1)); return; } if (re->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) { re->dw_read = _read_msb; re->dw_decode = _decode_msb; } else { re->dw_read = _read_lsb; re->dw_decode = _decode_lsb; } if (re->options & ~RE_H) load_sections(re); if ((re->options & RE_VV) || (re->options & RE_S)) search_ver(re); if (re->options & RE_H) dump_ehdr(re); if (re->options & RE_L) dump_phdr(re); if (re->options & RE_SS) dump_shdr(re); if (re->options & RE_D) dump_dynamic(re); if (re->options & RE_R) dump_reloc(re); if (re->options & RE_S) dump_symtabs(re); if (re->options & RE_N) dump_notes(re); if (re->options & RE_II) dump_hash(re); if (re->options & RE_X) hex_dump(re); if (re->options & RE_P) str_dump(re); if (re->options & RE_VV) dump_ver(re); if (re->options & RE_AA) dump_arch_specific_info(re); if (re->options & RE_W) dump_dwarf(re); if (re->options & ~RE_H) unload_sections(re); } static void dump_dwarf(struct readelf *re) { int error; Dwarf_Error de; if (dwarf_elf_init(re->elf, DW_DLC_READ, NULL, NULL, &re->dbg, &de)) { if ((error = dwarf_errno(de)) != DW_DLE_DEBUG_INFO_NULL) errx(EXIT_FAILURE, "dwarf_elf_init failed: %s", dwarf_errmsg(de)); return; } if (re->dop & DW_A) dump_dwarf_abbrev(re); if (re->dop & DW_L) dump_dwarf_line(re); if (re->dop & DW_LL) dump_dwarf_line_decoded(re); if (re->dop & DW_I) { dump_dwarf_info(re, 0); dump_dwarf_info(re, 1); } if (re->dop & DW_P) dump_dwarf_pubnames(re); if (re->dop & DW_R) dump_dwarf_aranges(re); if (re->dop & DW_RR) dump_dwarf_ranges(re); if (re->dop & DW_M) dump_dwarf_macinfo(re); if (re->dop & DW_F) dump_dwarf_frame(re, 0); else if (re->dop & DW_FF) dump_dwarf_frame(re, 1); if (re->dop & DW_S) dump_dwarf_str(re); if (re->dop & DW_O) dump_dwarf_loclist(re); dwarf_finish(re->dbg, &de); } static void dump_ar(struct readelf *re, int fd) { Elf_Arsym *arsym; Elf_Arhdr *arhdr; Elf_Cmd cmd; Elf *e; size_t sz; off_t off; int i; re->ar = re->elf; if (re->options & RE_C) { if ((arsym = elf_getarsym(re->ar, &sz)) == NULL) { warnx("elf_getarsym() failed: %s", elf_errmsg(-1)); goto process_members; } printf("Index of archive %s: (%ju entries)\n", re->filename, (uintmax_t) sz - 1); off = 0; for (i = 0; (size_t) i < sz; i++) { if (arsym[i].as_name == NULL) break; if (arsym[i].as_off != off) { off = arsym[i].as_off; if (elf_rand(re->ar, off) != off) { warnx("elf_rand() failed: %s", elf_errmsg(-1)); continue; } if ((e = elf_begin(fd, ELF_C_READ, re->ar)) == NULL) { warnx("elf_begin() failed: %s", elf_errmsg(-1)); continue; } if ((arhdr = elf_getarhdr(e)) == NULL) { warnx("elf_getarhdr() failed: %s", elf_errmsg(-1)); elf_end(e); continue; } printf("Binary %s(%s) contains:\n", re->filename, arhdr->ar_name); } printf("\t%s\n", arsym[i].as_name); } if (elf_rand(re->ar, SARMAG) != SARMAG) { warnx("elf_rand() failed: %s", elf_errmsg(-1)); return; } } process_members: if ((re->options & ~RE_C) == 0) return; cmd = ELF_C_READ; while ((re->elf = elf_begin(fd, cmd, re->ar)) != NULL) { if ((arhdr = elf_getarhdr(re->elf)) == NULL) { warnx("elf_getarhdr() failed: %s", elf_errmsg(-1)); goto next_member; } if (strcmp(arhdr->ar_name, "/") == 0 || strcmp(arhdr->ar_name, "//") == 0 || strcmp(arhdr->ar_name, "__.SYMDEF") == 0) goto next_member; printf("\nFile: %s(%s)\n", re->filename, arhdr->ar_name); dump_elf(re); next_member: cmd = elf_next(re->elf); elf_end(re->elf); } re->elf = re->ar; } static void dump_object(struct readelf *re) { int fd; if ((fd = open(re->filename, O_RDONLY)) == -1) { warn("open %s failed", re->filename); return; } if ((re->flags & DISPLAY_FILENAME) != 0) printf("\nFile: %s\n", re->filename); if ((re->elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { warnx("elf_begin() failed: %s", elf_errmsg(-1)); return; } switch (elf_kind(re->elf)) { case ELF_K_NONE: warnx("Not an ELF file."); return; case ELF_K_ELF: dump_elf(re); break; case ELF_K_AR: dump_ar(re, fd); break; default: warnx("Internal: libelf returned unknown elf kind."); return; } elf_end(re->elf); } static void add_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t) { struct dumpop *d; if ((d = find_dumpop(re, si, sn, -1, t)) == NULL) { if ((d = calloc(1, sizeof(*d))) == NULL) err(EXIT_FAILURE, "calloc failed"); if (t == DUMP_BY_INDEX) d->u.si = si; else d->u.sn = sn; d->type = t; d->op = op; STAILQ_INSERT_TAIL(&re->v_dumpop, d, dumpop_list); } else d->op |= op; } static struct dumpop * find_dumpop(struct readelf *re, size_t si, const char *sn, int op, int t) { struct dumpop *d; STAILQ_FOREACH(d, &re->v_dumpop, dumpop_list) { if ((op == -1 || op & d->op) && (t == -1 || (unsigned) t == d->type)) { if ((d->type == DUMP_BY_INDEX && d->u.si == si) || (d->type == DUMP_BY_NAME && !strcmp(d->u.sn, sn))) return (d); } } return (NULL); } static struct { const char *ln; char sn; int value; } dwarf_op[] = { {"rawline", 'l', DW_L}, {"decodedline", 'L', DW_LL}, {"info", 'i', DW_I}, {"abbrev", 'a', DW_A}, {"pubnames", 'p', DW_P}, {"aranges", 'r', DW_R}, {"ranges", 'r', DW_R}, {"Ranges", 'R', DW_RR}, {"macro", 'm', DW_M}, {"frames", 'f', DW_F}, {"frames-interp", 'F', DW_FF}, {"str", 's', DW_S}, {"loc", 'o', DW_O}, {NULL, 0, 0} }; static void parse_dwarf_op_short(struct readelf *re, const char *op) { int i; if (op == NULL) { re->dop |= DW_DEFAULT_OPTIONS; return; } for (; *op != '\0'; op++) { for (i = 0; dwarf_op[i].ln != NULL; i++) { if (dwarf_op[i].sn == *op) { re->dop |= dwarf_op[i].value; break; } } } } static void parse_dwarf_op_long(struct readelf *re, const char *op) { char *p, *token, *bp; int i; if (op == NULL) { re->dop |= DW_DEFAULT_OPTIONS; return; } if ((p = strdup(op)) == NULL) err(EXIT_FAILURE, "strdup failed"); bp = p; while ((token = strsep(&p, ",")) != NULL) { for (i = 0; dwarf_op[i].ln != NULL; i++) { if (!strcmp(token, dwarf_op[i].ln)) { re->dop |= dwarf_op[i].value; break; } } } free(bp); } static uint64_t _read_lsb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read) { uint64_t ret; uint8_t *src; src = (uint8_t *) d->d_buf + *offsetp; ret = 0; switch (bytes_to_read) { case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; case 2: ret |= ((uint64_t) src[1]) << 8; case 1: ret |= src[0]; break; default: return (0); } *offsetp += bytes_to_read; return (ret); } static uint64_t _read_msb(Elf_Data *d, uint64_t *offsetp, int bytes_to_read) { uint64_t ret; uint8_t *src; src = (uint8_t *) d->d_buf + *offsetp; switch (bytes_to_read) { case 1: ret = src[0]; break; case 2: ret = src[1] | ((uint64_t) src[0]) << 8; break; case 4: ret = src[3] | ((uint64_t) src[2]) << 8; ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; break; case 8: ret = src[7] | ((uint64_t) src[6]) << 8; ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; break; default: return (0); } *offsetp += bytes_to_read; return (ret); } static uint64_t _decode_lsb(uint8_t **data, int bytes_to_read) { uint64_t ret; uint8_t *src; src = *data; ret = 0; switch (bytes_to_read) { case 8: ret |= ((uint64_t) src[4]) << 32 | ((uint64_t) src[5]) << 40; ret |= ((uint64_t) src[6]) << 48 | ((uint64_t) src[7]) << 56; case 4: ret |= ((uint64_t) src[2]) << 16 | ((uint64_t) src[3]) << 24; case 2: ret |= ((uint64_t) src[1]) << 8; case 1: ret |= src[0]; break; default: return (0); } *data += bytes_to_read; return (ret); } static uint64_t _decode_msb(uint8_t **data, int bytes_to_read) { uint64_t ret; uint8_t *src; src = *data; ret = 0; switch (bytes_to_read) { case 1: ret = src[0]; break; case 2: ret = src[1] | ((uint64_t) src[0]) << 8; break; case 4: ret = src[3] | ((uint64_t) src[2]) << 8; ret |= ((uint64_t) src[1]) << 16 | ((uint64_t) src[0]) << 24; break; case 8: ret = src[7] | ((uint64_t) src[6]) << 8; ret |= ((uint64_t) src[5]) << 16 | ((uint64_t) src[4]) << 24; ret |= ((uint64_t) src[3]) << 32 | ((uint64_t) src[2]) << 40; ret |= ((uint64_t) src[1]) << 48 | ((uint64_t) src[0]) << 56; break; default: return (0); break; } *data += bytes_to_read; return (ret); } static int64_t _decode_sleb128(uint8_t **dp) { int64_t ret = 0; uint8_t b; int shift = 0; uint8_t *src = *dp; do { b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; } while ((b & 0x80) != 0); if (shift < 32 && (b & 0x40) != 0) ret |= (-1 << shift); *dp = src; return (ret); } static uint64_t _decode_uleb128(uint8_t **dp) { uint64_t ret = 0; uint8_t b; int shift = 0; uint8_t *src = *dp; do { b = *src++; ret |= ((b & 0x7f) << shift); shift += 7; } while ((b & 0x80) != 0); *dp = src; return (ret); } static void readelf_version(void) { (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(EXIT_SUCCESS); } #define USAGE_MESSAGE "\ Usage: %s [options] file...\n\ Display information about ELF objects and ar(1) archives.\n\n\ Options:\n\ -a | --all Equivalent to specifying options '-dhIlrsASV'.\n\ -c | --archive-index Print the archive symbol table for archives.\n\ -d | --dynamic Print the contents of SHT_DYNAMIC sections.\n\ -e | --headers Print all headers in the object.\n\ -g | --section-groups (accepted, but ignored)\n\ -h | --file-header Print the file header for the object.\n\ -l | --program-headers Print the PHDR table for the object.\n\ -n | --notes Print the contents of SHT_NOTE sections.\n\ -p INDEX | --string-dump=INDEX\n\ Print the contents of section at index INDEX.\n\ -r | --relocs Print relocation information.\n\ -s | --syms | --symbols Print symbol tables.\n\ -t | --section-details Print additional information about sections.\n\ -v | --version Print a version identifier and exit.\n\ -x INDEX | --hex-dump=INDEX\n\ Display contents of a section as hexadecimal.\n\ -A | --arch-specific (accepted, but ignored)\n\ -D | --use-dynamic Print the symbol table specified by the DT_SYMTAB\n\ entry in the \".dynamic\" section.\n\ -H | --help Print a help message.\n\ -I | --histogram Print information on bucket list lengths for \n\ hash sections.\n\ -N | --full-section-name (accepted, but ignored)\n\ -S | --sections | --section-headers\n\ Print information about section headers.\n\ -V | --version-info Print symbol versoning information.\n\ -W | --wide Print information without wrapping long lines.\n" static void readelf_usage(void) { fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } int main(int argc, char **argv) { struct readelf *re, re_storage; unsigned long si; int opt, i; char *ep; re = &re_storage; memset(re, 0, sizeof(*re)); STAILQ_INIT(&re->v_dumpop); while ((opt = getopt_long(argc, argv, "AacDdegHhIi:lNnp:rSstuVvWw::x:", longopts, NULL)) != -1) { switch(opt) { case '?': readelf_usage(); break; case 'A': re->options |= RE_AA; break; case 'a': re->options |= RE_AA | RE_D | RE_H | RE_II | RE_L | RE_R | RE_SS | RE_S | RE_VV; break; case 'c': re->options |= RE_C; break; case 'D': re->options |= RE_DD; break; case 'd': re->options |= RE_D; break; case 'e': re->options |= RE_H | RE_L | RE_SS; break; case 'g': re->options |= RE_G; break; case 'H': readelf_usage(); break; case 'h': re->options |= RE_H; break; case 'I': re->options |= RE_II; break; case 'i': /* Not implemented yet. */ break; case 'l': re->options |= RE_L; break; case 'N': re->options |= RE_NN; break; case 'n': re->options |= RE_N; break; case 'p': re->options |= RE_P; si = strtoul(optarg, &ep, 10); if (*ep == '\0') add_dumpop(re, (size_t) si, NULL, STR_DUMP, DUMP_BY_INDEX); else add_dumpop(re, 0, optarg, STR_DUMP, DUMP_BY_NAME); break; case 'r': re->options |= RE_R; break; case 'S': re->options |= RE_SS; break; case 's': re->options |= RE_S; break; case 't': re->options |= RE_T; break; case 'u': re->options |= RE_U; break; case 'V': re->options |= RE_VV; break; case 'v': readelf_version(); break; case 'W': re->options |= RE_WW; break; case 'w': re->options |= RE_W; parse_dwarf_op_short(re, optarg); break; case 'x': re->options |= RE_X; si = strtoul(optarg, &ep, 10); if (*ep == '\0') add_dumpop(re, (size_t) si, NULL, HEX_DUMP, DUMP_BY_INDEX); else add_dumpop(re, 0, optarg, HEX_DUMP, DUMP_BY_NAME); break; case OPTION_DEBUG_DUMP: re->options |= RE_W; parse_dwarf_op_long(re, optarg); } } argv += optind; argc -= optind; if (argc == 0 || re->options == 0) readelf_usage(); if (argc > 1) re->flags |= DISPLAY_FILENAME; if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization failed: %s", elf_errmsg(-1)); for (i = 0; i < argc; i++) if (argv[i] != NULL) { re->filename = argv[i]; dump_object(re); } exit(EXIT_SUCCESS); } Index: head/contrib/elftoolchain/size/size.c =================================================================== --- head/contrib/elftoolchain/size/size.c (revision 280931) +++ head/contrib/elftoolchain/size/size.c (revision 280932) @@ -1,918 +1,917 @@ /*- * Copyright (c) 2007 S.Sam Arun Raj * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: size.c 2350 2011-12-19 10:20:06Z jkoshy $"); +ELFTC_VCSID("$Id: size.c 3174 2015-03-27 17:13:41Z emaste $"); #define BUF_SIZE 1024 #define ELF_ALIGN(val,x) (((val)+(x)-1) & ~((x)-1)) #define SIZE_VERSION_STRING "size 1.0" enum return_code { RETURN_OK, RETURN_NOINPUT, RETURN_DATAERR, RETURN_USAGE }; enum output_style { STYLE_BERKELEY, STYLE_SYSV }; enum radix_style { RADIX_OCTAL, RADIX_DECIMAL, RADIX_HEX }; static uint64_t bss_size, data_size, text_size, total_size; static uint64_t bss_size_total, data_size_total, text_size_total; static int show_totals; static int size_option; static enum radix_style radix = RADIX_DECIMAL; static enum output_style style = STYLE_BERKELEY; static const char *default_args[2] = { "a.out", NULL }; static struct { int row; int col; int *width; char ***tbl; } *tb; enum { OPT_FORMAT, OPT_RADIX }; static struct option size_longopts[] = { { "format", required_argument, &size_option, OPT_FORMAT }, { "help", no_argument, NULL, 'h' }, { "radix", required_argument, &size_option, OPT_RADIX }, { "totals", no_argument, NULL, 't' }, { "version", no_argument, NULL, 'V' }, { NULL, 0, NULL, 0 } }; static void berkeley_calc(GElf_Shdr *); static void berkeley_footer(const char *, const char *, const char *); static void berkeley_header(void); static void berkeley_totals(void); static int handle_core(char const *, Elf *elf, GElf_Ehdr *); static void handle_core_note(Elf *, GElf_Ehdr *, GElf_Phdr *, char **); static int handle_elf(char const *); static void handle_phdr(Elf *, GElf_Ehdr *, GElf_Phdr *, uint32_t, const char *); static void show_version(void); static void sysv_header(const char *, Elf_Arhdr *); static void sysv_footer(void); static void sysv_calc(Elf *, GElf_Ehdr *, GElf_Shdr *); static void usage(void); static void tbl_new(int); static void tbl_print(const char *, int); static void tbl_print_num(uint64_t, enum radix_style, int); static void tbl_append(void); static void tbl_flush(void); /* * size utility using elf(3) and gelf(3) API to list section sizes and * total in elf files. Supports only elf files (core dumps in elf * included) that can be opened by libelf, other formats are not supported. */ int main(int argc, char **argv) { int ch, r, rc; const char **files, *fn; rc = RETURN_OK; if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization failed: %s", elf_errmsg(-1)); while ((ch = getopt_long(argc, argv, "ABVdhotx", size_longopts, NULL)) != -1) switch((char)ch) { case 'A': style = STYLE_SYSV; break; case 'B': style = STYLE_BERKELEY; break; case 'V': show_version(); break; case 'd': radix = RADIX_DECIMAL; break; case 'o': radix = RADIX_OCTAL; break; case 't': show_totals = 1; break; case 'x': radix = RADIX_HEX; break; case 0: switch (size_option) { case OPT_FORMAT: if (*optarg == 's' || *optarg == 'S') style = STYLE_SYSV; else if (*optarg == 'b' || *optarg == 'B') style = STYLE_BERKELEY; else { warnx("unrecognized format \"%s\".", optarg); usage(); } break; case OPT_RADIX: r = strtol(optarg, NULL, 10); if (r == 8) radix = RADIX_OCTAL; else if (r == 10) radix = RADIX_DECIMAL; else if (r == 16) radix = RADIX_HEX; else { warnx("unsupported radix \"%s\".", optarg); usage(); } break; default: err(EXIT_FAILURE, "Error in option handling."); /*NOTREACHED*/ } break; case 'h': case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; files = (argc == 0) ? default_args : (void *) argv; while ((fn = *files) != NULL) { rc = handle_elf(fn); if (rc != RETURN_OK) warnx(rc == RETURN_NOINPUT ? "'%s': No such file" : "%s: File format not recognized", fn); files++; } if (style == STYLE_BERKELEY) { if (show_totals) berkeley_totals(); tbl_flush(); } return (rc); } static Elf_Data * xlatetom(Elf *elf, GElf_Ehdr *elfhdr, void *_src, void *_dst, Elf_Type type, size_t size) { Elf_Data src, dst; src.d_buf = _src; src.d_type = type; src.d_version = elfhdr->e_version; src.d_size = size; dst.d_buf = _dst; dst.d_version = elfhdr->e_version; dst.d_size = size; return (gelf_xlatetom(elf, &dst, &src, elfhdr->e_ident[EI_DATA])); } #define NOTE_OFFSET_32(nhdr, namesz, offset) \ ((char *)nhdr + sizeof(Elf32_Nhdr) + \ ELF_ALIGN((int32_t)namesz, 4) + offset) #define NOTE_OFFSET_64(nhdr, namesz, offset) \ ((char *)nhdr + sizeof(Elf32_Nhdr) + \ ELF_ALIGN((int32_t)namesz, 8) + offset) #define PID32(nhdr, namesz, offset) \ (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_32(nhdr, \ namesz, offset))); #define PID64(nhdr, namesz, offset) \ (pid_t)*((int *)((uintptr_t)NOTE_OFFSET_64(nhdr, \ namesz, offset))); #define NEXT_NOTE(elfhdr, descsz, namesz, offset) do { \ if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { \ offset += ELF_ALIGN((int32_t)descsz, 4) + \ sizeof(Elf32_Nhdr) + \ ELF_ALIGN((int32_t)namesz, 4); \ } else { \ offset += ELF_ALIGN((int32_t)descsz, 8) + \ sizeof(Elf32_Nhdr) + \ ELF_ALIGN((int32_t)namesz, 8); \ } \ } while (0) /* * Parse individual note entries inside a PT_NOTE segment. */ static void handle_core_note(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr, char **cmd_line) { size_t max_size; uint64_t raw_size; GElf_Off offset; static pid_t pid; uintptr_t ver; Elf32_Nhdr *nhdr, nhdr_l; static int reg_pseudo = 0, reg2_pseudo = 0 /*, regxfp_pseudo = 0*/; char buf[BUF_SIZE], *data, *name; if (elf == NULL || elfhdr == NULL || phdr == NULL) return; data = elf_rawfile(elf, &max_size); offset = phdr->p_offset; while (data != NULL && offset < phdr->p_offset + phdr->p_filesz) { nhdr = (Elf32_Nhdr *)(uintptr_t)((char*)data + offset); memset(&nhdr_l, 0, sizeof(Elf32_Nhdr)); if (!xlatetom(elf, elfhdr, &nhdr->n_type, &nhdr_l.n_type, ELF_T_WORD, sizeof(Elf32_Word)) || !xlatetom(elf, elfhdr, &nhdr->n_descsz, &nhdr_l.n_descsz, ELF_T_WORD, sizeof(Elf32_Word)) || !xlatetom(elf, elfhdr, &nhdr->n_namesz, &nhdr_l.n_namesz, ELF_T_WORD, sizeof(Elf32_Word))) break; name = (char *)((char *)nhdr + sizeof(Elf32_Nhdr)); switch (nhdr_l.n_type) { case NT_PRSTATUS: { raw_size = 0; if (elfhdr->e_ident[EI_OSABI] == ELFOSABI_FREEBSD && nhdr_l.n_namesz == 0x8 && !strcmp(name,"FreeBSD")) { if (elfhdr->e_ident[EI_CLASS] == ELFCLASS32) { raw_size = (uint64_t)*((uint32_t *) (uintptr_t)(name + ELF_ALIGN((int32_t) nhdr_l.n_namesz, 4) + 8)); ver = (uintptr_t)NOTE_OFFSET_32(nhdr, nhdr_l.n_namesz,0); if (*((int *)ver) == 1) pid = PID32(nhdr, nhdr_l.n_namesz, 24); } else { raw_size = *((uint64_t *)(uintptr_t) (name + ELF_ALIGN((int32_t) nhdr_l.n_namesz, 8) + 16)); ver = (uintptr_t)NOTE_OFFSET_64(nhdr, nhdr_l.n_namesz,0); if (*((int *)ver) == 1) pid = PID64(nhdr, nhdr_l.n_namesz, 40); } xlatetom(elf, elfhdr, &raw_size, &raw_size, ELF_T_WORD, sizeof(uint64_t)); xlatetom(elf, elfhdr, &pid, &pid, ELF_T_WORD, sizeof(pid_t)); } if (raw_size != 0 && style == STYLE_SYSV) { (void) snprintf(buf, BUF_SIZE, "%s/%d", ".reg", pid); tbl_append(); tbl_print(buf, 0); tbl_print_num(raw_size, radix, 1); tbl_print_num(0, radix, 2); if (!reg_pseudo) { tbl_append(); tbl_print(".reg", 0); tbl_print_num(raw_size, radix, 1); tbl_print_num(0, radix, 2); reg_pseudo = 1; text_size_total += raw_size; } text_size_total += raw_size; } } break; case NT_FPREGSET: /* same as NT_PRFPREG */ if (style == STYLE_SYSV) { (void) snprintf(buf, BUF_SIZE, "%s/%d", ".reg2", pid); tbl_append(); tbl_print(buf, 0); tbl_print_num(nhdr_l.n_descsz, radix, 1); tbl_print_num(0, radix, 2); if (!reg2_pseudo) { tbl_append(); tbl_print(".reg2", 0); tbl_print_num(nhdr_l.n_descsz, radix, 1); tbl_print_num(0, radix, 2); reg2_pseudo = 1; text_size_total += nhdr_l.n_descsz; } text_size_total += nhdr_l.n_descsz; } break; #if 0 case NT_AUXV: if (style == STYLE_SYSV) { tbl_append(); tbl_print(".auxv", 0); tbl_print_num(nhdr_l.n_descsz, radix, 1); tbl_print_num(0, radix, 2); text_size_total += nhdr_l.n_descsz; } break; case NT_PRXFPREG: if (style == STYLE_SYSV) { (void) snprintf(buf, BUF_SIZE, "%s/%d", ".reg-xfp", pid); tbl_append(); tbl_print(buf, 0); tbl_print_num(nhdr_l.n_descsz, radix, 1); tbl_print_num(0, radix, 2); if (!regxfp_pseudo) { tbl_append(); tbl_print(".reg-xfp", 0); tbl_print_num(nhdr_l.n_descsz, radix, 1); tbl_print_num(0, radix, 2); regxfp_pseudo = 1; text_size_total += nhdr_l.n_descsz; } text_size_total += nhdr_l.n_descsz; } break; case NT_PSINFO: #endif case NT_PRPSINFO: { /* FreeBSD 64-bit */ if (nhdr_l.n_descsz == 0x78 && !strcmp(name,"FreeBSD")) { *cmd_line = strdup(NOTE_OFFSET_64(nhdr, nhdr_l.n_namesz, 33)); /* FreeBSD 32-bit */ } else if (nhdr_l.n_descsz == 0x6c && !strcmp(name,"FreeBSD")) { *cmd_line = strdup(NOTE_OFFSET_32(nhdr, nhdr_l.n_namesz, 25)); } /* Strip any trailing spaces */ if (*cmd_line != NULL) { char *s; s = *cmd_line + strlen(*cmd_line); while (s > *cmd_line) { if (*(s-1) != 0x20) break; s--; } *s = 0; } break; } #if 0 case NT_PSTATUS: case NT_LWPSTATUS: #endif default: break; } NEXT_NOTE(elfhdr, nhdr_l.n_descsz, nhdr_l.n_namesz, offset); } } /* * Handles program headers except for PT_NOTE, when sysv output stlye is * choosen, prints out the segment name and length. For berkely output * style only PT_LOAD segments are handled, and text, * data, bss size is calculated for them. */ static void handle_phdr(Elf *elf, GElf_Ehdr *elfhdr, GElf_Phdr *phdr, uint32_t idx, const char *name) { uint64_t addr, size; int split; char buf[BUF_SIZE]; if (elf == NULL || elfhdr == NULL || phdr == NULL) return; size = addr = 0; split = (phdr->p_memsz > 0) && (phdr->p_filesz > 0) && (phdr->p_memsz > phdr->p_filesz); if (style == STYLE_SYSV) { (void) snprintf(buf, BUF_SIZE, "%s%d%s", name, idx, (split ? "a" : "")); tbl_append(); tbl_print(buf, 0); tbl_print_num(phdr->p_filesz, radix, 1); tbl_print_num(phdr->p_vaddr, radix, 2); text_size_total += phdr->p_filesz; if (split) { size = phdr->p_memsz - phdr->p_filesz; addr = phdr->p_vaddr + phdr->p_filesz; (void) snprintf(buf, BUF_SIZE, "%s%d%s", name, idx, "b"); text_size_total += phdr->p_memsz - phdr->p_filesz; tbl_append(); tbl_print(buf, 0); tbl_print_num(size, radix, 1); tbl_print_num(addr, radix, 2); } } else { if (phdr->p_type != PT_LOAD) return; if ((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) { data_size += phdr->p_filesz; if (split) data_size += phdr->p_memsz - phdr->p_filesz; } else { text_size += phdr->p_filesz; if (split) text_size += phdr->p_memsz - phdr->p_filesz; } } } /* * Given a core dump file, this function maps program headers to segments. */ static int handle_core(char const *name, Elf *elf, GElf_Ehdr *elfhdr) { GElf_Phdr phdr; uint32_t i; char *core_cmdline; const char *seg_name; if (name == NULL || elf == NULL || elfhdr == NULL) return (RETURN_DATAERR); if (elfhdr->e_shnum != 0 || elfhdr->e_type != ET_CORE) return (RETURN_DATAERR); seg_name = core_cmdline = NULL; if (style == STYLE_SYSV) sysv_header(name, NULL); else berkeley_header(); for (i = 0; i < elfhdr->e_phnum; i++) { if (gelf_getphdr(elf, i, &phdr) != NULL) { if (phdr.p_type == PT_NOTE) { handle_phdr(elf, elfhdr, &phdr, i, "note"); handle_core_note(elf, elfhdr, &phdr, &core_cmdline); } else { switch(phdr.p_type) { case PT_NULL: seg_name = "null"; break; case PT_LOAD: seg_name = "load"; break; case PT_DYNAMIC: seg_name = "dynamic"; break; case PT_INTERP: seg_name = "interp"; break; case PT_SHLIB: seg_name = "shlib"; break; case PT_PHDR: seg_name = "phdr"; break; case PT_GNU_EH_FRAME: seg_name = "eh_frame_hdr"; break; case PT_GNU_STACK: seg_name = "stack"; break; default: seg_name = "segment"; } handle_phdr(elf, elfhdr, &phdr, i, seg_name); } } } if (style == STYLE_BERKELEY) { if (core_cmdline != NULL) { berkeley_footer(core_cmdline, name, "core file invoked as"); } else { berkeley_footer(core_cmdline, name, "core file"); } } else { sysv_footer(); if (core_cmdline != NULL) { (void) printf(" (core file invoked as %s)\n\n", core_cmdline); } else { (void) printf(" (core file)\n\n"); } } free(core_cmdline); return (RETURN_OK); } /* * Given an elf object,ar(1) filename, and based on the output style * and radix format the various sections and their length will be printed * or the size of the text, data, bss sections will be printed out. */ static int handle_elf(char const *name) { GElf_Ehdr elfhdr; GElf_Shdr shdr; Elf *elf, *elf1; Elf_Arhdr *arhdr; Elf_Scn *scn; Elf_Cmd elf_cmd; int exit_code, fd; if (name == NULL) return (RETURN_NOINPUT); if ((fd = open(name, O_RDONLY, 0)) < 0) return (RETURN_NOINPUT); elf_cmd = ELF_C_READ; elf1 = elf_begin(fd, elf_cmd, NULL); while ((elf = elf_begin(fd, elf_cmd, elf1)) != NULL) { arhdr = elf_getarhdr(elf); if (elf_kind(elf) == ELF_K_NONE && arhdr == NULL) { (void) elf_end(elf); (void) elf_end(elf1); (void) close(fd); return (RETURN_DATAERR); } if (elf_kind(elf) != ELF_K_ELF || (gelf_getehdr(elf, &elfhdr) == NULL)) { elf_cmd = elf_next(elf); (void) elf_end(elf); warnx("%s: File format not recognized", arhdr->ar_name); continue; } /* Core dumps are handled seperately */ if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { exit_code = handle_core(name, elf, &elfhdr); (void) elf_end(elf); (void) elf_end(elf1); (void) close(fd); return (exit_code); } else { scn = NULL; if (style == STYLE_BERKELEY) { berkeley_header(); while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != NULL) berkeley_calc(&shdr); } } else { sysv_header(name, arhdr); scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) != NULL) sysv_calc(elf, &elfhdr, &shdr); } } if (style == STYLE_BERKELEY) { if (arhdr != NULL) { berkeley_footer(name, arhdr->ar_name, "ex"); } else { berkeley_footer(name, NULL, "ex"); } } else { sysv_footer(); } } elf_cmd = elf_next(elf); (void) elf_end(elf); } (void) elf_end(elf1); (void) close(fd); return (RETURN_OK); } /* * Sysv formatting helper functions. */ static void sysv_header(const char *name, Elf_Arhdr *arhdr) { text_size_total = 0; if (arhdr != NULL) (void) printf("%s (ex %s):\n", arhdr->ar_name, name); else (void) printf("%s :\n", name); tbl_new(3); tbl_append(); tbl_print("section", 0); tbl_print("size", 1); tbl_print("addr", 2); } static void sysv_calc(Elf *elf, GElf_Ehdr *elfhdr, GElf_Shdr *shdr) { char *section_name; section_name = elf_strptr(elf, elfhdr->e_shstrndx, (size_t) shdr->sh_name); if ((shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_STRTAB || shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL) && shdr->sh_addr == 0) return; tbl_append(); tbl_print(section_name, 0); tbl_print_num(shdr->sh_size, radix, 1); tbl_print_num(shdr->sh_addr, radix, 2); text_size_total += shdr->sh_size; } static void sysv_footer(void) { tbl_append(); tbl_print("Total", 0); tbl_print_num(text_size_total, radix, 1); tbl_flush(); putchar('\n'); } /* * berkeley style output formatting helper functions. */ static void berkeley_header(void) { static int printed; text_size = data_size = bss_size = 0; if (!printed) { tbl_new(6); tbl_append(); tbl_print("text", 0); tbl_print("data", 1); tbl_print("bss", 2); if (radix == RADIX_OCTAL) tbl_print("oct", 3); else tbl_print("dec", 3); tbl_print("hex", 4); tbl_print("filename", 5); printed = 1; } } static void berkeley_calc(GElf_Shdr *shdr) { if (shdr != NULL) { if (!(shdr->sh_flags & SHF_ALLOC)) return; if ((shdr->sh_flags & SHF_ALLOC) && ((shdr->sh_flags & SHF_EXECINSTR) || !(shdr->sh_flags & SHF_WRITE))) text_size += shdr->sh_size; else if ((shdr->sh_flags & SHF_ALLOC) && (shdr->sh_flags & SHF_WRITE) && (shdr->sh_type != SHT_NOBITS)) data_size += shdr->sh_size; else bss_size += shdr->sh_size; } } static void berkeley_totals(void) { long unsigned int grand_total; grand_total = text_size_total + data_size_total + bss_size_total; tbl_append(); tbl_print_num(text_size_total, radix, 0); tbl_print_num(data_size_total, radix, 1); tbl_print_num(bss_size_total, radix, 2); if (radix == RADIX_OCTAL) tbl_print_num(grand_total, RADIX_OCTAL, 3); else tbl_print_num(grand_total, RADIX_DECIMAL, 3); tbl_print_num(grand_total, RADIX_HEX, 4); } static void berkeley_footer(const char *name, const char *ar_name, const char *msg) { char buf[BUF_SIZE]; total_size = text_size + data_size + bss_size; if (show_totals) { text_size_total += text_size; bss_size_total += bss_size; data_size_total += data_size; } tbl_append(); tbl_print_num(text_size, radix, 0); tbl_print_num(data_size, radix, 1); tbl_print_num(bss_size, radix, 2); if (radix == RADIX_OCTAL) tbl_print_num(total_size, RADIX_OCTAL, 3); else tbl_print_num(total_size, RADIX_DECIMAL, 3); tbl_print_num(total_size, RADIX_HEX, 4); if (ar_name != NULL && name != NULL) (void) snprintf(buf, BUF_SIZE, "%s (%s %s)", ar_name, msg, name); else if (ar_name != NULL && name == NULL) (void) snprintf(buf, BUF_SIZE, "%s (%s)", ar_name, msg); else (void) snprintf(buf, BUF_SIZE, "%s", name); tbl_print(buf, 5); } static void tbl_new(int col) { assert(tb == NULL); assert(col > 0); if ((tb = calloc(1, sizeof(*tb))) == NULL) err(EXIT_FAILURE, "calloc"); if ((tb->tbl = calloc(col, sizeof(*tb->tbl))) == NULL) err(EXIT_FAILURE, "calloc"); if ((tb->width = calloc(col, sizeof(*tb->width))) == NULL) err(EXIT_FAILURE, "calloc"); tb->col = col; tb->row = 0; } static void tbl_print(const char *s, int col) { int len; assert(tb != NULL && tb->col > 0 && tb->row > 0 && col < tb->col); assert(s != NULL && tb->tbl[col][tb->row - 1] == NULL); if ((tb->tbl[col][tb->row - 1] = strdup(s)) == NULL) err(EXIT_FAILURE, "strdup"); len = strlen(s); if (len > tb->width[col]) tb->width[col] = len; } static void tbl_print_num(uint64_t num, enum radix_style rad, int col) { char buf[BUF_SIZE]; (void) snprintf(buf, BUF_SIZE, (rad == RADIX_DECIMAL ? "%ju" : ((rad == RADIX_OCTAL) ? "0%jo" : "0x%jx")), (uintmax_t) num); tbl_print(buf, col); } static void tbl_append(void) { int i; assert(tb != NULL && tb->col > 0); tb->row++; for (i = 0; i < tb->col; i++) { tb->tbl[i] = realloc(tb->tbl[i], sizeof(*tb->tbl[i]) * tb->row); if (tb->tbl[i] == NULL) err(EXIT_FAILURE, "realloc"); tb->tbl[i][tb->row - 1] = NULL; } } static void tbl_flush(void) { const char *str; int i, j; if (tb == NULL) return; assert(tb->col > 0); for (i = 0; i < tb->row; i++) { if (style == STYLE_BERKELEY) printf(" "); for (j = 0; j < tb->col; j++) { str = (tb->tbl[j][i] != NULL ? tb->tbl[j][i] : ""); if (style == STYLE_SYSV && j == 0) printf("%-*s", tb->width[j], str); else if (style == STYLE_BERKELEY && j == tb->col - 1) printf("%s", str); else printf("%*s", tb->width[j], str); if (j == tb->col -1) putchar('\n'); else printf(" "); } } for (i = 0; i < tb->col; i++) { for (j = 0; j < tb->row; j++) { if (tb->tbl[i][j]) free(tb->tbl[i][j]); } free(tb->tbl[i]); } free(tb->tbl); free(tb->width); free(tb); tb = NULL; } #define USAGE_MESSAGE "\ Usage: %s [options] file ...\n\ Display sizes of ELF sections.\n\n\ Options:\n\ --format=format Display output in specified format. Supported\n\ values are `berkeley' and `sysv'.\n\ --help Display this help message and exit.\n\ --radix=radix Display numeric values in the specified radix.\n\ Supported values are: 8, 10 and 16.\n\ --totals Show cumulative totals of section sizes.\n\ --version Display a version identifier and exit.\n\ -A Equivalent to `--format=sysv'.\n\ -B Equivalent to `--format=berkeley'.\n\ -V Equivalent to `--version'.\n\ -d Equivalent to `--radix=10'.\n\ -h Same as option --help.\n\ -o Equivalent to `--radix=8'.\n\ -t Equivalent to option --totals.\n\ -x Equivalent to `--radix=16'.\n" static void usage(void) { (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } static void show_version(void) { (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(EXIT_SUCCESS); } Index: head/contrib/elftoolchain/strings/strings.c =================================================================== --- head/contrib/elftoolchain/strings/strings.c (revision 280931) +++ head/contrib/elftoolchain/strings/strings.c (revision 280932) @@ -1,454 +1,453 @@ /*- * Copyright (c) 2007 S.Sam Arun Raj * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ -#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "_elftc.h" -ELFTC_VCSID("$Id: strings.c 3124 2014-12-21 05:46:28Z kaiwang27 $"); +ELFTC_VCSID("$Id: strings.c 3174 2015-03-27 17:13:41Z emaste $"); enum return_code { RETURN_OK, RETURN_NOINPUT, RETURN_SOFTWARE }; enum radix_style { RADIX_DECIMAL, RADIX_HEX, RADIX_OCTAL }; enum encoding_style { ENCODING_7BIT, ENCODING_8BIT, ENCODING_16BIT_BIG, ENCODING_16BIT_LITTLE, ENCODING_32BIT_BIG, ENCODING_32BIT_LITTLE }; #define PRINTABLE(c) \ ((c) >= 0 && (c) <= 255 && \ ((c) == '\t' || isprint((c)) || \ (encoding == ENCODING_8BIT && (c) > 127))) static int encoding_size, entire_file, min_len, show_filename, show_loc; static enum encoding_style encoding; static enum radix_style radix; static struct option strings_longopts[] = { { "all", no_argument, NULL, 'a'}, { "bytes", required_argument, NULL, 'n'}, { "encoding", required_argument, NULL, 'e'}, { "help", no_argument, NULL, 'h'}, { "print-file-name", no_argument, NULL, 'f'}, { "radix", required_argument, NULL, 't'}, { "version", no_argument, NULL, 'v'}, { NULL, 0, NULL, 0 } }; long getcharacter(void); int handle_file(const char *); int handle_elf(const char *, int); int handle_binary(const char *, int); int find_strings(const char *, off_t, off_t); void show_version(void); void usage(void); /* * strings(1) extracts text(contiguous printable characters) * from elf and binary files. */ int main(int argc, char **argv) { int ch, rc; rc = RETURN_OK; min_len = 0; encoding_size = 1; if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization failed: %s", elf_errmsg(-1)); while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv", strings_longopts, NULL)) != -1) switch((char)ch) { case 'a': entire_file = 1; break; case 'e': if (*optarg == 's') { encoding = ENCODING_7BIT; } else if (*optarg == 'S') { encoding = ENCODING_8BIT; } else if (*optarg == 'b') { encoding = ENCODING_16BIT_BIG; encoding_size = 2; } else if (*optarg == 'B') { encoding = ENCODING_32BIT_BIG; encoding_size = 4; } else if (*optarg == 'l') { encoding = ENCODING_16BIT_LITTLE; encoding_size = 2; } else if (*optarg == 'L') { encoding = ENCODING_32BIT_LITTLE; encoding_size = 4; } else usage(); /* NOTREACHED */ break; case 'f': show_filename = 1; break; case 'n': min_len = (int)strtoimax(optarg, (char**)NULL, 10); break; case 'o': show_loc = 1; radix = RADIX_OCTAL; break; case 't': show_loc = 1; if (*optarg == 'd') radix = RADIX_DECIMAL; else if (*optarg == 'o') radix = RADIX_OCTAL; else if (*optarg == 'x') radix = RADIX_HEX; else usage(); /* NOTREACHED */ break; case 'v': case 'V': show_version(); /* NOTREACHED */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': min_len *= 10; min_len += ch - '0'; break; case 'h': case '?': default: usage(); /* NOTREACHED */ } argc -= optind; argv += optind; if (!min_len) min_len = 4; if (!*argv) rc = handle_file("{standard input}"); else while (*argv) { rc = handle_file(*argv); argv++; } return (rc); } int handle_file(const char *name) { int fd, rt; if (name == NULL) return (RETURN_NOINPUT); if (strcmp("{standard input}", name) != 0) { if (freopen(name, "rb", stdin) == NULL) { warnx("'%s': %s", name, strerror(errno)); return (RETURN_NOINPUT); } } else { return (find_strings(name, (off_t)0, (off_t)0)); } fd = fileno(stdin); if (fd < 0) return (RETURN_NOINPUT); rt = handle_elf(name, fd); return (rt); } /* * Files not understood by handle_elf, will be passed off here and will * treated as a binary file. This would include text file, core dumps ... */ int handle_binary(const char *name, int fd) { struct stat buf; memset(&buf, 0, sizeof(struct stat)); (void) lseek(fd, (off_t)0, SEEK_SET); if (!fstat(fd, &buf)) return (find_strings(name, (off_t)0, buf.st_size)); return (RETURN_SOFTWARE); } /* * Will analyse a file to see if it ELF, other files including ar(1), * core dumps are passed off and treated as flat binary files. Unlike * GNU size in FreeBSD this routine will not treat ELF object from * different archs as flat binary files(has to overridden using -a). */ int handle_elf(const char *name, int fd) { GElf_Ehdr elfhdr; GElf_Shdr shdr; Elf *elf; Elf_Scn *scn; int rc; rc = RETURN_OK; /* If entire file is choosen, treat it as a binary file */ if (entire_file) return (handle_binary(name, fd)); (void) lseek(fd, (off_t)0, SEEK_SET); elf = elf_begin(fd, ELF_C_READ, NULL); if (elf_kind(elf) != ELF_K_ELF) { (void) elf_end(elf); return (handle_binary(name, fd)); } if (gelf_getehdr(elf, &elfhdr) == NULL) { (void) elf_end(elf); warnx("%s: ELF file could not be processed", name); return (RETURN_SOFTWARE); } if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { (void) elf_end(elf); return (handle_binary(name, fd)); } else { scn = NULL; while ((scn = elf_nextscn(elf, scn)) != NULL) { if (gelf_getshdr(scn, &shdr) == NULL) continue; if (shdr.sh_type != SHT_NOBITS && (shdr.sh_flags & SHF_ALLOC) != 0) { rc = find_strings(name, shdr.sh_offset, shdr.sh_size); } } } (void) elf_end(elf); return (rc); } /* * Retrieves a character from input stream based on the encoding * type requested. */ long getcharacter(void) { long rt; int i; char buf[4], c; rt = EOF; for(i = 0; i < encoding_size; i++) { c = getc(stdin); if (feof(stdin)) return (EOF); buf[i] = c; } switch(encoding) { case ENCODING_7BIT: case ENCODING_8BIT: rt = buf[0]; break; case ENCODING_16BIT_BIG: rt = (buf[0] << 8) | buf[1]; break; case ENCODING_16BIT_LITTLE: rt = buf[0] | (buf[1] << 8); break; case ENCODING_32BIT_BIG: rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) | ((long) buf[2] << 8) | buf[3]; break; case ENCODING_32BIT_LITTLE: rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) | ((long) buf[3] << 24); break; } return (rt); } /* * Input stream stdin is read until the end of file is reached or until * the section size is reached in case of ELF files. Contiguous * characters of >= min_size(default 4) will be displayed. */ int find_strings(const char *name, off_t offset, off_t size) { off_t cur_off, start_off; char *obuf; long c; int i; if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) { (void) fprintf(stderr, "Unable to allocate memory: %s\n", strerror(errno)); return (RETURN_SOFTWARE); } (void) fseeko(stdin, offset, SEEK_SET); cur_off = offset; start_off = 0; while(1) { if ((offset + size) && (cur_off >= offset + size)) break; start_off = cur_off; memset(obuf, 0, min_len+1); for(i = 0; i < min_len; i++) { c = getcharacter(); if (c == EOF && feof(stdin)) goto _exit1; if (PRINTABLE(c)) { obuf[i] = c; obuf[i+1] = 0; cur_off += encoding_size; } else { if (encoding == ENCODING_8BIT && (uint8_t)c > 127) { obuf[i] = c; obuf[i+1] = 0; cur_off += encoding_size; continue; } cur_off += encoding_size; break; } } if (i >= min_len && ((cur_off <= offset + size) || !(offset + size))) { if (show_filename) printf ("%s: ", name); if (show_loc) { switch(radix) { case RADIX_DECIMAL: (void) printf("%7ju ", (uintmax_t)start_off); break; case RADIX_HEX: (void) printf("%7jx ", (uintmax_t)start_off); break; case RADIX_OCTAL: (void) printf("%7jo ", (uintmax_t)start_off); break; } } printf("%s", obuf); while(1) { if ((offset + size) && (cur_off >= offset + size)) break; c = getcharacter(); cur_off += encoding_size; if (encoding == ENCODING_8BIT && (uint8_t)c > 127) { putchar(c); continue; } if (!PRINTABLE(c) || c == EOF) break; putchar(c); } putchar('\n'); } } _exit1: free(obuf); return (RETURN_OK); } #define USAGE_MESSAGE "\ Usage: %s [options] [file...]\n\ Print contiguous sequences of printable characters.\n\n\ Options:\n\ -a | --all Scan the entire file for strings.\n\ -e ENC | --encoding=ENC Select the character encoding to use.\n\ -f | --print-file-name Print the file name before each string.\n\ -h | --help Print a help message and exit.\n\ -n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\ -o Print offsets in octal.\n\ -t R | --radix=R Print offsets using the radix named by 'R'.\n\ -v | --version Print a version identifier and exit.\n" void usage(void) { (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); exit(EXIT_FAILURE); } void show_version(void) { (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); exit(EXIT_SUCCESS); } Index: head/contrib/elftoolchain =================================================================== --- head/contrib/elftoolchain (revision 280931) +++ head/contrib/elftoolchain (revision 280932) Property changes on: head/contrib/elftoolchain ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /vendor/elftoolchain/dist:r280917