diff options
| author | Roland McGrath <[email protected]> | 2007-10-04 08:50:09 +0000 |
|---|---|---|
| committer | Roland McGrath <[email protected]> | 2007-10-04 08:50:09 +0000 |
| commit | 59ea7f33f781e6e3f8c9d81d457e5d99eee8f1ce (patch) | |
| tree | 10a3dd35d3b568876f0edc6dd903fe8715a507e1 /libelf | |
| parent | 057ec6b35ef97bd1cf6c1e96da3da399237e5224 (diff) | |
src/
2007-10-04 Roland McGrath <[email protected]>
* readelf.c (print_archive_index): New variable.
(options, parse_opt): Accept -c/--archive-index to set it.
(dump_archive_index): New function.
(process_file): Take new arg WILL_PRINT_ARCHIVE_INDEX.
Call dump_archive_index on archives if set.
(main): Update caller.
(any_control_option): Give it file scope, moved out of ...
(parse_opt): ... here.
tests/
2007-10-04 Roland McGrath <[email protected]>
* run-readelf-test4.sh: New file.
* Makefile.am (TESTS, EXTRA_DIST): Add it.
Diffstat (limited to 'libelf')
| -rw-r--r-- | libelf/ChangeLog | 24 | ||||
| -rw-r--r-- | libelf/Makefile.am | 2 | ||||
| -rw-r--r-- | libelf/elf_end.c | 20 | ||||
| -rw-r--r-- | libelf/elf_getdata_rawchunk.c (renamed from libelf/gelf_rawchunk.c) | 144 | ||||
| -rw-r--r-- | libelf/gelf.h | 7 | ||||
| -rw-r--r-- | libelf/gelf_freechunk.c | 78 | ||||
| -rw-r--r-- | libelf/libelf.h | 17 | ||||
| -rw-r--r-- | libelf/libelf.map | 3 | ||||
| -rw-r--r-- | libelf/libelfP.h | 15 |
9 files changed, 183 insertions, 127 deletions
diff --git a/libelf/ChangeLog b/libelf/ChangeLog index c879aede..1532a4cf 100644 --- a/libelf/ChangeLog +++ b/libelf/ChangeLog @@ -1,3 +1,27 @@ +2007-10-04 Roland McGrath <[email protected]> + + * elf_end.c (elf_end): Don't free ELF->state.ar.ar_sym when it's -1l. + +2007-10-03 Roland McGrath <[email protected]> + + * libelf.h (Elf_Data): Use off64_t for d_off. + (Elf_Arhdr): Use off64_t for ar_size. + (elf_update, elf_getbase, elf_getaroff): Return off64_t. + + * gelf_rawchunk.c: File removed. + * gelf_freechunk.c: File removed. + * Makefile.am (libelf_a_SOURCES): Remove them. + * libelf.map (ELFUTILS_1.0): Remove exports. + * gelf.h: Remove decls. + + * elf_getdata_rawchunk.c: New file. + * Makefile.am (libelf_a_SOURCES): Add it. + * libelf.map (ELFUTILS_1.3): Add elf_getdata_rawchunk. + * libelf.h: Declare it. + * libelfP.h (Elf_Data_Chunk): New type. + (struct Elf.elf): New member `rawchunks'. + * elf_end.c (elf_end): Free recorded rawchunk buffers. + 2007-08-24 Roland McGrath <[email protected]> * gelf_getnote.c: New file. diff --git a/libelf/Makefile.am b/libelf/Makefile.am index 3e52bcec..58c9b5a8 100644 --- a/libelf/Makefile.am +++ b/libelf/Makefile.am @@ -71,6 +71,7 @@ libelf_a_SOURCES = elf_version.c elf_hash.c elf_error.c elf_fill.c \ elf32_getshdr.c elf64_getshdr.c gelf_getshdr.c \ gelf_update_shdr.c \ elf_strptr.c elf_rawdata.c elf_getdata.c elf_newdata.c \ + elf_getdata_rawchunk.c \ elf_flagelf.c elf_flagehdr.c elf_flagphdr.c elf_flagscn.c \ elf_flagshdr.c elf_flagdata.c elf_memory.c \ elf_update.c elf32_updatenull.c elf64_updatenull.c \ @@ -93,7 +94,6 @@ libelf_a_SOURCES = elf_version.c elf_hash.c elf_error.c elf_fill.c \ gelf_update_verdaux.c \ elf_getshnum.c elf_getshstrndx.c \ gelf_checksum.c elf32_checksum.c elf64_checksum.c \ - gelf_rawchunk.c gelf_freechunk.c \ libelf_crc32.c libelf_next_prime.c \ elf_clone.c \ gelf_getlib.c gelf_update_lib.c \ diff --git a/libelf/elf_end.c b/libelf/elf_end.c index 4b4e11fe..5112eaea 100644 --- a/libelf/elf_end.c +++ b/libelf/elf_end.c @@ -1,5 +1,5 @@ /* Free resources associated with Elf descriptor. - Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Red Hat, Inc. + Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007 Red Hat, Inc. This file is part of Red Hat elfutils. Written by Ulrich Drepper <[email protected]>, 1998. @@ -89,7 +89,8 @@ elf_end (elf) descriptor. The long name table cannot be freed yet since the archive headers for the ELF files in the archive point into this array. */ - free (elf->state.ar.ar_sym); + if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l) + free (elf->state.ar.ar_sym); elf->state.ar.ar_sym = NULL; if (elf->state.ar.children != NULL) @@ -134,6 +135,21 @@ elf_end (elf) case ELF_K_ELF: { + Elf_Data_Chunk *rawchunks + = (elf->class == ELFCLASS32 + || (offsetof (struct Elf, state.elf32.rawchunks) + == offsetof (struct Elf, state.elf64.rawchunks)) + ? elf->state.elf32.rawchunks + : elf->state.elf64.rawchunks); + while (rawchunks != NULL) + { + Elf_Data_Chunk *next = rawchunks->next; + if (rawchunks->dummy_scn.flags & ELF_F_MALLOCED) + free (rawchunks->data.d.d_buf); + free (rawchunks); + rawchunks = next; + } + Elf_ScnList *list = (elf->class == ELFCLASS32 || (offsetof (struct Elf, state.elf32.scns) == offsetof (struct Elf, state.elf64.scns)) diff --git a/libelf/gelf_rawchunk.c b/libelf/elf_getdata_rawchunk.c index ced6f9ef..bea0f3f6 100644 --- a/libelf/gelf_rawchunk.c +++ b/libelf/elf_getdata_rawchunk.c @@ -1,7 +1,6 @@ -/* Retrieve uninterpreted chunk of the file contents. - Copyright (C) 2002, 2005, 2007 Red Hat, Inc. +/* Return converted data from raw chunk of ELF file. + Copyright (C) 2007 Red Hat, Inc. This file is part of Red Hat elfutils. - Contributed by Ulrich Drepper <[email protected]>, 2002. Red Hat elfutils is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -52,57 +51,138 @@ # include <config.h> #endif +#include <assert.h> #include <errno.h> -#include <libelf.h> -#include <stddef.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <system.h> #include "libelfP.h" +#include "common.h" - -char * -gelf_rawchunk (elf, offset, size) +Elf_Data * +elf_getdata_rawchunk (elf, offset, size, type) Elf *elf; - GElf_Off offset; - GElf_Word size; + off64_t offset; + size_t size; + Elf_Type type; { - if (elf == NULL) + if (unlikely (elf == NULL)) + return NULL; + + if (unlikely (elf->kind != ELF_K_ELF)) { /* No valid descriptor. */ __libelf_seterrno (ELF_E_INVALID_HANDLE); return NULL; } - if (unlikely (offset >= elf->maximum_size - || offset + size >= elf->maximum_size - || offset + size < offset)) + if (unlikely (size > elf->maximum_size + || (off64_t) (elf->maximum_size - size) < offset)) { /* Invalid request. */ __libelf_seterrno (ELF_E_INVALID_OP); return NULL; } - /* If the file is mmap'ed return an appropriate pointer. */ + if (type >= ELF_T_NUM) + { + __libelf_seterrno (ELF_E_UNKNOWN_TYPE); + return NULL; + } + + /* Get the raw bytes from the file. */ + void *rawchunk; + int flags = 0; + + /* If the file is mmap'ed we can use it directly. */ if (elf->map_address != NULL) - return (char *) elf->map_address + elf->start_offset + offset; + rawchunk = elf->map_address + elf->start_offset + offset; + else + { + /* We allocate the memory and read the data from the file. */ + rawchunk = malloc (size); + if (rawchunk == NULL) + { + nomem: + __libelf_seterrno (ELF_E_NOMEM); + return NULL; + } + + /* Read the file content. */ + if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size, + elf->start_offset + offset) + != size)) + { + /* Something went wrong. */ + free (rawchunk); + __libelf_seterrno (ELF_E_READ_ERROR); + return NULL; + } - /* We allocate the memory and read the data from the file. */ - char *result = (char *) malloc (size); - if (result == NULL) - __libelf_seterrno (ELF_E_NOMEM); + flags = ELF_F_MALLOCED; + } + + /* Copy and/or convert the data as needed for aligned native-order access. */ + size_t align = __libelf_type_align (elf->class, type); + void *buffer; + if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA) + { + if (((uintptr_t) rawchunk & (align - 1)) == 0) + /* No need to copy, we can use the raw data. */ + buffer = rawchunk; + else + { + /* A malloc'd block is always sufficiently aligned. */ + assert (flags == 0); + + buffer = malloc (size); + if (unlikely (buffer == NULL)) + goto nomem; + flags = ELF_F_MALLOCED; + + /* The copy will be appropriately aligned for direct access. */ + memcpy (buffer, rawchunk, size); + } + } else - /* Read the file content. */ - if (unlikely ((size_t) pread_retry (elf->fildes, result, size, - elf->start_offset + offset) - != size)) - { - /* Something went wrong. */ - __libelf_seterrno (ELF_E_READ_ERROR); - free (result); - result = NULL; - } - - return result; + { + if (flags) + buffer = rawchunk; + else + { + buffer = malloc (size); + if (unlikely (buffer == NULL)) + goto nomem; + flags = ELF_F_MALLOCED; + } + + /* Call the conversion function. */ + (*__elf_xfctstom[LIBELF_EV_IDX][LIBELF_EV_IDX][elf->class - 1][type]) + (buffer, rawchunk, size, 0); + } + + /* Allocate the dummy container to point at this buffer. */ + Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk); + if (chunk == NULL) + { + if (flags) + free (buffer); + goto nomem; + } + + chunk->dummy_scn.elf = elf; + chunk->dummy_scn.flags = flags; + chunk->data.s = &chunk->dummy_scn; + chunk->data.d.d_buf = buffer; + chunk->data.d.d_size = size; + chunk->data.d.d_type = type; + chunk->data.d.d_align = align; + chunk->data.d.d_version = __libelf_version; + + chunk->next = elf->state.elf.rawchunks; + elf->state.elf.rawchunks = chunk; + + return &chunk->data.d; } diff --git a/libelf/gelf.h b/libelf/gelf.h index 9f81b7e9..533e15a9 100644 --- a/libelf/gelf.h +++ b/libelf/gelf.h @@ -343,13 +343,6 @@ extern size_t gelf_getnote (Elf_Data *__data, size_t __offset, size_t *__name_offset, size_t *__desc_offset); -/* Retrieve uninterpreted chunk of the file contents. */ -extern char *gelf_rawchunk (Elf *__elf, GElf_Off __offset, GElf_Word __size); - -/* Release uninterpreted chunk of the file contents. */ -extern void gelf_freechunk (Elf *__elf, char *__ptr); - - /* Compute simple checksum from permanent parts of the ELF file. */ extern long int gelf_checksum (Elf *__elf); diff --git a/libelf/gelf_freechunk.c b/libelf/gelf_freechunk.c deleted file mode 100644 index 7b293ab0..00000000 --- a/libelf/gelf_freechunk.c +++ /dev/null @@ -1,78 +0,0 @@ -/* Release uninterpreted chunk of the file contents. - Copyright (C) 2002 Red Hat, Inc. - This file is part of Red Hat elfutils. - Contributed by Ulrich Drepper <[email protected]>, 2002. - - Red Hat elfutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by the - Free Software Foundation; version 2 of the License. - - Red Hat elfutils is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License along - with Red Hat elfutils; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. - - In addition, as a special exception, Red Hat, Inc. gives You the - additional right to link the code of Red Hat elfutils with code licensed - under any Open Source Initiative certified open source license - (http://www.opensource.org/licenses/index.php) which requires the - distribution of source code with any binary distribution and to - distribute linked combinations of the two. Non-GPL Code permitted under - this exception must only link to the code of Red Hat elfutils through - those well defined interfaces identified in the file named EXCEPTION - found in the source code files (the "Approved Interfaces"). The files - of Non-GPL Code may instantiate templates or use macros or inline - functions from the Approved Interfaces without causing the resulting - work to be covered by the GNU General Public License. Only Red Hat, - Inc. may make changes or additions to the list of Approved Interfaces. - Red Hat's grant of this exception is conditioned upon your not adding - any new exceptions. If you wish to add a new Approved Interface or - exception, please contact Red Hat. You must obey the GNU General Public - License in all respects for all of the Red Hat elfutils code and other - code used in conjunction with Red Hat elfutils except the Non-GPL Code - covered by this exception. If you modify this file, you may extend this - exception to your version of the file, but you are not obligated to do - so. If you do not wish to provide this exception without modification, - you must delete this exception statement from your version and license - this file solely under the GPL without exception. - - Red Hat elfutils is an included package of the Open Invention Network. - An included package of the Open Invention Network is a package for which - Open Invention Network licensees cross-license their patents. No patent - license is granted, either expressly or impliedly, by designation as an - included package. Should you wish to participate in the Open Invention - Network licensing program, please visit www.openinventionnetwork.com - <http://www.openinventionnetwork.com>. */ - -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include <libelf.h> -#include <stddef.h> -#include <stdlib.h> - -#include "libelfP.h" - - -void -gelf_freechunk (elf, ptr) - Elf *elf; - char *ptr; -{ - if (elf == NULL) - /* No valid descriptor. */ - return; - - /* We do not have to do anything if the pointer returned by - gelf_rawchunk points into the memory allocated for the ELF - descriptor. */ - if (ptr < (char *) elf->map_address + elf->start_offset - || ptr >= ((char *) elf->map_address + elf->start_offset - + elf->maximum_size)) - free (ptr); -} diff --git a/libelf/libelf.h b/libelf/libelf.h index a5d744cf..bd8dcb09 100644 --- a/libelf/libelf.h +++ b/libelf/libelf.h @@ -95,7 +95,7 @@ typedef struct Elf_Type d_type; /* Type of this piece of data. */ unsigned int d_version; /* ELF version. */ size_t d_size; /* Size in bytes. */ - off_t d_off; /* Offset into section. */ + off64_t d_off; /* Offset into section. */ size_t d_align; /* Alignment in section. */ } Elf_Data; @@ -157,7 +157,7 @@ typedef struct uid_t ar_uid; /* User ID. */ gid_t ar_gid; /* Group ID. */ mode_t ar_mode; /* File mode. */ - off_t ar_size; /* File size. */ + off64_t ar_size; /* File size. */ char *ar_rawname; /* Original name of archive member. */ } Elf_Arhdr; @@ -198,13 +198,13 @@ extern Elf_Cmd elf_next (Elf *__elf); extern int elf_end (Elf *__elf); /* Update ELF descriptor and write file to disk. */ -extern off_t elf_update (Elf *__elf, Elf_Cmd __cmd); +extern off64_t elf_update (Elf *__elf, Elf_Cmd __cmd); /* Determine what kind of file is associated with ELF. */ extern Elf_Kind elf_kind (Elf *__elf) __attribute__ ((__pure__)); /* Get the base offset for an object file. */ -extern off_t elf_getbase (Elf *__elf); +extern off64_t elf_getbase (Elf *__elf); /* Retrieve file identification data. */ @@ -298,6 +298,13 @@ extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data); /* Create new data descriptor for section SCN. */ extern Elf_Data *elf_newdata (Elf_Scn *__scn); +/* Get data translated from a chunk of the file contents as section data + would be for TYPE. The resulting Elf_Data pointer is valid until + elf_end (ELF) is called. */ +extern Elf_Data *elf_getdata_rawchunk (Elf *__elf, + off64_t __offset, size_t __size, + Elf_Type __type); + /* Return pointer to string at OFFSET in section INDEX. */ extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset); @@ -307,7 +314,7 @@ extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset); extern Elf_Arhdr *elf_getarhdr (Elf *__elf); /* Return offset in archive for current file ELF. */ -extern off_t elf_getaroff (Elf *__elf); +extern off64_t elf_getaroff (Elf *__elf); /* Select archive element at OFFSET. */ extern size_t elf_rand (Elf *__elf, size_t __offset); diff --git a/libelf/libelf.map b/libelf/libelf.map index 9453c438..aaaf9164 100644 --- a/libelf/libelf.map +++ b/libelf/libelf.map @@ -55,7 +55,6 @@ ELFUTILS_1.0 { elf_update; elf_version; gelf_checksum; - gelf_freechunk; gelf_fsize; gelf_getclass; gelf_getdyn; @@ -75,7 +74,6 @@ ELFUTILS_1.0 { gelf_getversym; gelf_newehdr; gelf_newphdr; - gelf_rawchunk; gelf_update_dyn; gelf_update_ehdr; gelf_update_move; @@ -120,6 +118,7 @@ ELFUTILS_1.2 { ELFUTILS_1.3 { global: + elf_getdata_rawchunk; gelf_getauxv; gelf_update_auxv; gelf_getnote; diff --git a/libelf/libelfP.h b/libelf/libelfP.h index 291206ca..7e6305cd 100644 --- a/libelf/libelfP.h +++ b/libelf/libelfP.h @@ -255,6 +255,18 @@ typedef struct Elf_ScnList } Elf_ScnList; +/* elf_getdata_rawchunk result. */ +typedef struct Elf_Data_Chunk +{ + Elf_Data_Scn data; + union + { + Elf_Scn dummy_scn; + struct Elf_Data_Chunk *next; + }; +} Elf_Data_Chunk; + + /* The ELF descriptor. */ struct Elf { @@ -313,6 +325,7 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ + Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ off64_t sizestr_offset; /* Offset of the size string in the parent @@ -332,6 +345,7 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ + Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ off64_t sizestr_offset; /* Offset of the size string in the parent @@ -357,6 +371,7 @@ struct Elf Elf_ScnList *scns_last; /* Last element in the section list. If NULL the data has not yet been read from the file. */ + Elf_Data_Chunk *rawchunks; /* List of elf_getdata_rawchunk results. */ unsigned int scnincr; /* Number of sections allocate the last time. */ off64_t sizestr_offset; /* Offset of the size string in the parent |
