summaryrefslogtreecommitdiffstats
path: root/libelf
diff options
context:
space:
mode:
authorRoland McGrath <[email protected]>2007-10-04 08:50:09 +0000
committerRoland McGrath <[email protected]>2007-10-04 08:50:09 +0000
commit59ea7f33f781e6e3f8c9d81d457e5d99eee8f1ce (patch)
tree10a3dd35d3b568876f0edc6dd903fe8715a507e1 /libelf
parent057ec6b35ef97bd1cf6c1e96da3da399237e5224 (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/ChangeLog24
-rw-r--r--libelf/Makefile.am2
-rw-r--r--libelf/elf_end.c20
-rw-r--r--libelf/elf_getdata_rawchunk.c (renamed from libelf/gelf_rawchunk.c)144
-rw-r--r--libelf/gelf.h7
-rw-r--r--libelf/gelf_freechunk.c78
-rw-r--r--libelf/libelf.h17
-rw-r--r--libelf/libelf.map3
-rw-r--r--libelf/libelfP.h15
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