diff options
Diffstat (limited to 'libelf/libelfP.h')
-rw-r--r-- | libelf/libelfP.h | 534 |
1 files changed, 534 insertions, 0 deletions
diff --git a/libelf/libelfP.h b/libelf/libelfP.h new file mode 100644 index 00000000..100f349a --- /dev/null +++ b/libelf/libelfP.h @@ -0,0 +1,534 @@ +/* Internal interfaces for libelf. + Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2005 Red Hat, Inc. + Contributed by Ulrich Drepper <drepper@redhat.com>, 1998. + + This program 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. + + This program 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 this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _LIBELFP_H +#define _LIBELFP_H 1 + +#include <ar.h> +#include <gelf.h> +#include <stdint.h> + +/* gettext helper macros. */ +#define _(Str) dgettext ("libelf", Str) + + +/* Helper Macros to write 32 bit and 64 bit functions. */ +#define __elfw2_(Bits, Name) __elf##Bits##_##Name +#define elfw2_(Bits, Name) elf##Bits##_##Name +#define ElfW2_(Bits, Name) Elf##Bits##_##Name +#define ELFW2_(Bits, Name) ELF##Bits##_##Name +#define ELFW_(Name, Bits) Name##Bits +#define __elfw2(Bits, Name) __elfw2_(Bits, Name) +#define elfw2(Bits, Name) elfw2_(Bits, Name) +#define ElfW2(Bits, Name) ElfW2_(Bits, Name) +#define ELFW2(Bits, Name) ELFW2_(Bits, Name) +#define ELFW(Name, Bits) ELFW_(Name, Bits) + + +/* Sizes of the external types, for 32 bits objects. */ +#define ELF32_FSZ_ADDR 4 +#define ELF32_FSZ_OFF 4 +#define ELF32_FSZ_HALF 2 +#define ELF32_FSZ_WORD 4 +#define ELF32_FSZ_SWORD 4 +#define ELF32_FSZ_XWORD 8 +#define ELF32_FSZ_SXWORD 8 + +/* Same for 64 bits objects. */ +#define ELF64_FSZ_ADDR 8 +#define ELF64_FSZ_OFF 8 +#define ELF64_FSZ_HALF 2 +#define ELF64_FSZ_WORD 4 +#define ELF64_FSZ_SWORD 4 +#define ELF64_FSZ_XWORD 8 +#define ELF64_FSZ_SXWORD 8 + + +/* This is an extension of the ELF_F_* enumeration. The values here are + not part of the library interface, they are only used internally. */ +enum +{ + ELF_F_MMAPPED = 0x40, + ELF_F_MALLOCED = 0x80, + ELF_F_FILEDATA = 0x100 +}; + + +/* Get definition of all the external types. */ +#include "exttypes.h" + + +/* Error values. */ +enum +{ + ELF_E_NOERROR = 0, + ELF_E_UNKNOWN_ERROR, + ELF_E_UNKNOWN_VERSION, + ELF_E_UNKNOWN_TYPE, + ELF_E_INVALID_HANDLE, + ELF_E_SOURCE_SIZE, + ELF_E_DEST_SIZE, + ELF_E_INVALID_ENCODING, + ELF_E_NOMEM, + ELF_E_INVALID_FILE, + ELF_E_INVALID_OP, + ELF_E_NO_VERSION, + ELF_E_INVALID_CMD, + ELF_E_RANGE, + ELF_E_ARCHIVE_FMAG, + ELF_E_INVALID_ARCHIVE, + ELF_E_NO_ARCHIVE, + ELF_E_NO_INDEX, + ELF_E_READ_ERROR, + ELF_E_WRITE_ERROR, + ELF_E_INVALID_CLASS, + ELF_E_INVALID_INDEX, + ELF_E_INVALID_OPERAND, + ELF_E_INVALID_SECTION, + ELF_E_INVALID_COMMAND, + ELF_E_WRONG_ORDER_EHDR, + ELF_E_FD_DISABLED, + ELF_E_FD_MISMATCH, + ELF_E_OFFSET_RANGE, + ELF_E_NOT_NUL_SECTION, + ELF_E_DATA_MISMATCH, + ELF_E_INVALID_SECTION_HEADER, + ELF_E_INVALID_DATA, + ELF_E_DATA_ENCODING, + ELF_E_SECTION_TOO_SMALL, + ELF_E_INVALID_ALIGN, + ELF_E_INVALID_SHENTSIZE, + ELF_E_UPDATE_RO, + ELF_E_NOFILE, + ELF_E_GROUP_NOT_REL, + ELF_E_INVALID_PHDR, + ELF_E_NO_PHDR, + /* Keep this as the last entry. */ + ELF_E_NUM +}; + + +/* The visible `Elf_Data' type is not sufficent for some operations due + to a misdesigned interface. Extend it for internal purposes. */ +typedef struct +{ + Elf_Data d; + Elf_Scn *s; +} Elf_Data_Scn; + + +/* List of `Elf_Data' descriptors. This is what makes up the section + contents. */ +typedef struct Elf_Data_List +{ + /* `data' *must* be the first element in the struct. */ + Elf_Data_Scn data; + struct Elf_Data_List *next; + int flags; +} Elf_Data_List; + + +/* Descriptor for ELF section. */ +struct Elf_Scn +{ + /* We have to distinguish several different situations: + + 1. the section is user created. Therefore there is no file or memory + region to read the data from. Here we have two different subcases: + + a) data was not yet added (before the first `elf_newdata' call) + + b) at least one data set is available + + 2. this is a section from a file/memory region. We have to read the + current content in one data block if we have to. But we don't + read the data until it is necessary. So we have the subcases: + + a) the section in the file has size zero (for whatever reason) + + b) the data of the file is not (yet) read + + c) the data is read and available. + + In addition to this we have different data sets, the raw and the converted + data. This distinction only exists for the data read from the file. + All user-added data set (all but the first when read from the file or + all of them for user-create sections) are the same in both formats. + We don't create the converted data before it is necessary. + + The `data_read' element signals whether data is available in the + raw format. + + If there is data from the file/memory region or if read one data + set is added the `rawdata_list_read' pointer in non-NULL and points + to the last filled data set. `raw_datalist_rear' is therefore NULL + only if there is no data set at all. + + This so far allows to distinguish all but two cases (given that the + `rawdata_list' and `data_list' entries are initialized to zero) is + between not yet loaded data from the file/memory region and a section + with zero size and type ELF_T_BYTE. */ + Elf_Data_List data_list; /* List of data buffers. */ + Elf_Data_List *data_list_rear; /* Pointer to the rear of the data list. */ + + Elf_Data_Scn rawdata; /* Uninterpreted data of the section. */ + + int data_read; /* Nonzero if the section was created by the + user or if the data from the file/memory + is read. */ + + size_t index; /* Index of this section. */ + struct Elf *elf; /* The underlying ELF file. */ + + union + { + Elf32_Shdr *e32; /* Pointer to 32bit section header. */ + Elf64_Shdr *e64; /* Pointer to 64bit section header. */ + } shdr; + + unsigned int shdr_flags; /* Section header modified? */ + unsigned int flags; /* Section changed in size? */ + + char *rawdata_base; /* The unmodified data of the section. */ + char *data_base; /* The converted data of the section. */ + + struct Elf_ScnList *list; /* Pointer the the section list element the + data is in. */ +}; + + +/* List of section. */ +typedef struct Elf_ScnList +{ + unsigned int cnt; /* Number of elements of 'data' used. */ + unsigned int max; /* Number of elements of 'data' allocated. */ + struct Elf_ScnList *next; /* Next block of sections. */ + struct Elf_Scn data[0]; /* Section data. */ +} Elf_ScnList; + + +/* The ELF descriptor. */ +struct Elf +{ + /* What kind of file is underneath (ELF file, archive...). */ + Elf_Kind kind; + + /* Command used to create this descriptor. */ + Elf_Cmd cmd; + + /* The binary class. */ + unsigned int class; + + /* The used file descriptor. -1 if not available anymore. */ + int fildes; + + /* Offset in the archive this file starts or zero. */ + off_t start_offset; + + /* Size of the file in the archive or the entire file size, or ~0 + for an (yet) unknown size. */ + size_t maximum_size; + + /* Address to which the file was mapped. NULL if not mapped. */ + void *map_address; + + /* Describes the way the memory was allocated and if the dirty bit is + signalled it means that the whole file has to be rewritten since + the layout changed. */ + int flags; + + /* When created for an archive member this points to the descriptor + for the archive. */ + Elf *parent; + + /* Lock to handle multithreaded programs. */ + rwlock_define (,lock); + + /* Reference counting for the descriptor. */ + int ref_count; + + struct Elf *next; /* Used in list of archive descriptors. */ + + union + { + struct + { + int ehdr_flags; /* Flags (dirty) for ELF header. */ + int phdr_flags; /* Flags (dirty|malloc) for program header. */ + int shdr_malloced; /* Nonzero if shdr array was allocated. */ + + /* The next fields are only useful when testing for ==/!= NULL. */ + void *ehdr; + void *shdr; + void *phdr; + + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + off64_t sizestr_offset; /* Offset of the size string in the parent + if this is an archive member. */ + } elf; + + struct + { + int ehdr_flags; /* Flags (dirty) for ELF header. */ + int phdr_flags; /* Flags (dirty|malloc) for program header. */ + int shdr_malloced; /* Nonzero if shdr array was allocated. */ + + Elf32_Ehdr *ehdr; /* Pointer to the ELF header. This is + never malloced. */ + Elf32_Shdr *shdr; /* Used when reading from a file. */ + Elf32_Phdr *phdr; /* Pointer to the program header array. */ + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + off64_t sizestr_offset; /* Offset of the size string in the parent + if this is an archive member. */ + Elf32_Ehdr ehdr_mem; /* Memory used for ELF header when not + mmaped. */ + char __e32scnspad[sizeof (Elf64_Ehdr) - sizeof (Elf32_Ehdr)]; + + /* The section array. */ + Elf_ScnList scns; + } elf32; + + struct + { + int ehdr_flags; /* Flags (dirty) for ELF header. */ + int phdr_flags; /* Flags (dirty|malloc) for program header. */ + int shdr_malloced; /* Nonzero if shdr array was allocated. */ + + Elf64_Ehdr *ehdr; /* Pointer to the ELF header. This is + never malloced. */ + Elf64_Shdr *shdr; /* Used when reading from a file. */ + Elf64_Phdr *phdr; /* Pointer to the program header array. */ + Elf_ScnList *scns_last; /* Last element in the section list. + If NULL the data has not yet been + read from the file. */ + unsigned int scnincr; /* Number of sections allocate the last + time. */ + off64_t sizestr_offset; /* Offset of the size string in the parent + if this is an archive member. */ + Elf64_Ehdr ehdr_mem; /* Memory used for ELF header when not + mmaped. */ + + /* The section array. */ + Elf_ScnList scns; + } elf64; + + struct + { + int has_index; /* Set when file has index. 0 means + undecided, > 0 means it has one. */ + Elf_Arsym *ar_sym; /* Symbol table returned by elf_getarsym. */ + size_t ar_sym_num; /* Number of entries in `ar_sym'. */ + char *long_names; /* If no index is available but long names + are used this elements points to the data.*/ + size_t long_names_len; /* Length of the long name table. */ + off_t offset; /* Offset in file we are currently at. + elf_next() advances this to the next + member of the archive. */ + Elf_Arhdr elf_ar_hdr; /* Structure returned by 'elf_getarhdr'. */ + struct ar_hdr ar_hdr; /* Header read from file. */ + char ar_name[16]; /* NUL terminated ar_name of elf_ar_hdr. */ + char raw_name[17]; /* This is a buffer for the NUL terminated + named raw_name used in the elf_ar_hdr. */ + struct Elf *children; /* List of all descriptors for this archive. */ + } ar; + } state; + + /* There absolutely never must be anything following the union. */ +}; + + +/* Type of the conversion functions. These functions will convert the + byte order. */ +typedef void (*xfct_t) (void *, const void *, size_t, int); + +/* The table with the function pointers. */ +extern const xfct_t __elf_xfctstom[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden; +extern const xfct_t __elf_xfctstof[EV_NUM - 1][EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden; + + +/* Array with sizes of the external types indexed by ELF version, binary + class, and type. */ +extern const size_t __libelf_type_sizes[EV_NUM - 1][ELFCLASSNUM - 1][ELF_T_NUM] attribute_hidden; +/* We often have to access the size for a type in the current version. */ +#if EV_NUM != 2 +# define elf_typesize(class,type,n) \ + elfw2(class,fsize) (type, n, __libelf_version) +#else +# define elf_typesize(class,type,n) \ + (__libelf_type_sizes[EV_CURRENT - 1][ELFW(ELFCLASS,class) - 1][type] * n) +#endif + +/* Currently selected version of the ELF specification. */ +extern unsigned int __libelf_version attribute_hidden; + +/* The byte value used for filling gaps. */ +extern int __libelf_fill_byte attribute_hidden; + +/* Nonzero if the version was set. */ +extern int __libelf_version_initialized attribute_hidden; + + +/* The libelf API does not have such a function but it is still useful. + Get the memory size for the given type. + + These functions cannot be marked internal since they are aliases + of the export elfXX_fsize functions.*/ +extern size_t __elf32_msize (Elf_Type __type, size_t __count, + unsigned int __version); +extern size_t __elf64_msize (Elf_Type __type, size_t __count, + unsigned int __version); + + +/* Create Elf descriptor from memory image. */ +extern Elf *__libelf_read_mmaped_file (int fildes, void *map_address, + off_t offset, size_t maxsize, + Elf_Cmd cmd, Elf *parent) + internal_function; + +/* Set error value. */ +extern void __libelf_seterrno (int value) internal_function; + +/* Get the next archive header. */ +extern int __libelf_next_arhdr (Elf *elf) internal_function; + +/* Read all of the file associated with the descriptor. */ +extern char *__libelf_readall (Elf *elf) internal_function; + +/* Read the complete section table and convert the byte order if necessary. */ +extern int __libelf_readsections (Elf *elf) internal_function; + +/* Store the information for the raw data in the `rawdata_list' element. */ +extern int __libelf_set_rawdata (Elf_Scn *scn) internal_function; + + +/* Helper functions for elf_update. */ +extern off_t __elf32_updatenull (Elf *elf, int *change_bop, size_t shnum) + internal_function; +extern off_t __elf64_updatenull (Elf *elf, int *change_bop, size_t shnum) + internal_function; + +extern int __elf32_updatemmap (Elf *elf, int change_bo, size_t shnum) + internal_function; +extern int __elf64_updatemmap (Elf *elf, int change_bo, size_t shnum) + internal_function; +extern int __elf32_updatefile (Elf *elf, int change_bo, size_t shnum) + internal_function; +extern int __elf64_updatefile (Elf *elf, int change_bo, size_t shnum) + internal_function; + + +/* Alias for exported functions to avoid PLT entries. */ +extern int __elf_end_internal (Elf *__elf); +extern Elf *__elf_begin_internal (int __fildes, Elf_Cmd __cmd, Elf *__ref) + attribute_hidden; +extern Elf32_Ehdr *__elf32_getehdr_internal (Elf *__elf) attribute_hidden; +extern Elf64_Ehdr *__elf64_getehdr_internal (Elf *__elf) attribute_hidden; +extern Elf32_Ehdr *__elf32_newehdr_internal (Elf *__elf) attribute_hidden; +extern Elf64_Ehdr *__elf64_newehdr_internal (Elf *__elf) attribute_hidden; +extern Elf32_Phdr *__elf32_getphdr_internal (Elf *__elf) attribute_hidden; +extern Elf64_Phdr *__elf64_getphdr_internal (Elf *__elf) attribute_hidden; +extern Elf32_Phdr *__elf32_newphdr_internal (Elf *__elf, size_t __cnt) + attribute_hidden; +extern Elf64_Phdr *__elf64_newphdr_internal (Elf *__elf, size_t __cnt) + attribute_hidden; +extern int __elf_getshnum_internal (Elf *__elf, size_t *__dst) + attribute_hidden; +extern int __elf_getshstrndx_internal (Elf *__elf, size_t *__dst) + attribute_hidden; +extern Elf32_Shdr *__elf32_getshdr_internal (Elf_Scn *__scn) attribute_hidden; +extern Elf64_Shdr *__elf64_getshdr_internal (Elf_Scn *__scn) attribute_hidden; +extern Elf_Scn *__elf_getscn_internal (Elf *__elf, size_t __index) + attribute_hidden; +extern Elf_Scn *__elf_nextscn_internal (Elf *__elf, Elf_Scn *__scn) + attribute_hidden; +extern Elf_Data *__elf_getdata_internal (Elf_Scn *__scn, Elf_Data *__data) + attribute_hidden; +extern Elf_Data *__elf_rawdata_internal (Elf_Scn *__scn, Elf_Data *__data) + attribute_hidden; +extern char *__elf_strptr_internal (Elf *__elf, size_t __index, + size_t __offset) attribute_hidden; +extern Elf_Data *__elf32_xlatetom_internal (Elf_Data *__dest, + const Elf_Data *__src, + unsigned int __encode) + attribute_hidden; +extern Elf_Data *__elf64_xlatetom_internal (Elf_Data *__dest, + const Elf_Data *__src, + unsigned int __encode) + attribute_hidden; +extern Elf_Data *__elf32_xlatetof_internal (Elf_Data *__dest, + const Elf_Data *__src, + unsigned int __encode) + attribute_hidden; +extern Elf_Data *__elf64_xlatetof_internal (Elf_Data *__dest, + const Elf_Data *__src, + unsigned int __encode) + attribute_hidden; +extern unsigned int __elf_version_internal (unsigned int __version) + attribute_hidden; +extern unsigned long int __elf_hash_internal (const char *__string) + __attribute__ ((__pure__, visibility ("hidden"))); +extern long int __elf32_checksum_internal (Elf *__elf) attribute_hidden; +extern long int __elf64_checksum_internal (Elf *__elf) attribute_hidden; + + +extern GElf_Ehdr *__gelf_getehdr_internal (Elf *__elf, GElf_Ehdr *__dest); +extern size_t __gelf_fsize_internal (Elf *__elf, Elf_Type __type, + size_t __count, unsigned int __version) + attribute_hidden; +extern GElf_Shdr *__gelf_getshdr_internal (Elf_Scn *__scn, GElf_Shdr *__dst) + attribute_hidden; +extern GElf_Sym *__gelf_getsym_internal (Elf_Data *__data, int __ndx, + GElf_Sym *__dst) attribute_hidden; + + +extern uint32_t __libelf_crc32 (uint32_t crc, unsigned char *buf, size_t len) + attribute_hidden; + + +/* We often have to update a flag iff a value changed. Make this + convenient. None of the parameters must have a side effect. */ +#ifdef __GNUC__ +# define update_if_changed(var, exp, flag) \ + do { \ + __typeof__ (var) *_var = &(var); \ + __typeof__ (exp) _exp = (exp); \ + if (*_var != _exp) \ + { \ + *_var = _exp; \ + (flag) |= ELF_F_DIRTY; \ + } \ + } while (0) +#else +# define update_if_changed(var, exp, flag) \ + do { \ + if ((var) != (exp)) \ + { \ + (var) = (exp); \ + (flag) |= ELF_F_DIRTY; \ + } \ + } while (0) +#endif + +#endif /* libelfP.h */ |