Migrate amdgpu-windows-interop to rocm-systems (#808)

这个提交包含在:
Joseph Macaranas
2025-09-05 10:32:44 -04:00
提交者 GitHub
父节点 3d9d35a1f8
当前提交 5ca7af2d30
修改 261 个文件,包含 86831 行新增2 行删除
@@ -0,0 +1,26 @@
##
########################################################################################################################
#
# Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
#
########################################################################################################################
cmake_minimum_required(VERSION 3.10)
file(GLOB sources
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
)
add_library(clCompilerElfLoader ${sources})
add_subdirectory(utils)
include_directories(${lib})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${elf-toolchain}/common)
if(WIN32)
include_directories(${elf-toolchain}/common/win32)
endif()
include_directories(${elf-toolchain}/libelf)
add_definitions(-DBSD_LIBELF)
文件差异内容过多而无法显示 加载差异
@@ -0,0 +1,416 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef ELF_HPP_
#define ELF_HPP_
#include <map>
#include "top.hpp"
#include "elf_utils.hpp"
#if !defined(WITH_LIGHTNING_COMPILER)
#include "caltarget.h" // using CALtargetEnum
#endif // !defined(WITH_LIGHTNING_COMPILER)
#include "libelf.h"
#include "gelf.h"
// Not sure where to put these in the libelf
#define AMD_BIF2 2 // AMD BIF Version 2.0
#define AMD_BIF3 3 // AMD BIF Version 3.0
// These two definitions need to stay in sync with
// the definitions elfdefinitions.h until they get
// properly upstreamed to gcc/libelf.
#ifndef EM_HSAIL
#define EM_HSAIL 0xAF5A
#endif
#ifndef EM_HSAIL_64
#define EM_HSAIL_64 0xAF5B
#endif
#ifndef EM_AMDIL
#define EM_AMDIL 0x4154
#endif
#ifndef EM_ATI_CALIMAGE_BINARY
#define EM_ATI_CALIMAGE_BINARY 125
#endif
#ifndef EM_AMDGPU
#define EM_AMDGPU 224
#endif
#ifndef ELFOSABI_AMD_OPENCL
#define ELFOSABI_AMD_OPENCL 201
#endif
#ifndef ELFOSABI_HSAIL
#define ELFOSABI_HSAIL 202
#endif
#ifndef ELFOSABI_AMDIL
#define ELFOSABI_AMDIL 203
#endif
#ifndef ELFOSABI_CALIMAGE
#define ELFOSABI_CALIMAGE 100
#endif
namespace amd {
// Test: is it ELF file (with a given bitness) ?
bool isElfHeader(const char* p, signed char ec);
bool isElfMagic(const char* p);
// Test: is it ELF for CAL ?
bool isCALTarget(const char* p, signed char ec);
// Symbol handle
typedef struct symbol_handle *Sym_Handle;
class OclElf
{
public:
enum {
CAL_BASE = 1001, // A number that is not dependent on libelf.h
CPU_BASE = 2001,
CPU_FEATURES_FIRST = 0, // Never generated, but keep it for simplicity.
CPU_FEATURES_LAST = 0xF // This should be consistent with cpudevice.hpp
} oclElfBase;
typedef enum {
// NOTE!!! Never remove an entry or change the order.
#if !defined(WITH_LIGHTNING_COMPILER)
// All CAL targets are within [CAL_FIRST, CAL_LAST].
CAL_FIRST = CAL_TARGET_600 + CAL_BASE,
CAL_LAST = CAL_TARGET_LAST + CAL_BASE,
#endif // !defined(WITH_LIGHTNING_COMPILER)
// All CPU targets are within [CPU_FIRST, CPU_LAST]
CPU_FIRST = CPU_FEATURES_FIRST + CPU_BASE,
CPU_LAST = CPU_FEATURES_LAST + CPU_BASE,
OCL_TARGETS_LAST,
} oclElfTargets;
typedef enum {
CAL_PLATFORM = 0,
CPU_PLATFORM = 1,
COMPLIB_PLATFORM = 2,
LC_PLATFORM = 3,
LAST_PLATFORM = 4
} oclElfPlatform;
typedef enum {
LLVMIR = 0,
SOURCE,
ILTEXT,
ASTEXT,
CAL,
DLL,
STRTAB,
SYMTAB,
RODATA,
SHSTRTAB,
NOTES,
COMMENT,
ILDEBUG,
DEBUG_INFO,
DEBUG_ABBREV,
DEBUG_LINE,
DEBUG_PUBNAMES,
DEBUG_PUBTYPES,
DEBUG_LOC,
DEBUG_ARANGES,
DEBUG_RANGES,
DEBUG_MACINFO,
DEBUG_STR,
DEBUG_FRAME,
JITBINARY,
CODEGEN,
TEXT,
INTERNAL,
SPIR,
SPIRV,
RUNTIME_METADATA,
OCL_ELF_SECTIONS_LAST
} oclElfSections;
typedef struct {
char* sec_name; //! section name
char* sec_addr; //! section address
uint64_t sec_size; //! section size
char* sym_name; //! symbol name
char* address; //! address of corresponding to symbol data
uint64_t size; //! size of data corresponding to symbol
} SymbolInfo;
private:
// file descriptor
int _fd;
// file name
const char* _fname;
// pointer to libelf structure
::Elf* _e;
// Error Object
mutable OclElfErr _err;
// Bitness of the Elf object.
unsigned char _eclass;
// Raw ELF bytes in memory from which Elf object is initialized
// The memory is owned by the client, not this OclElf object !
const char* _rawElfBytes;
uint64_t _rawElfSize;
// Read, write, or read and write for this Elf object
const Elf_Cmd _elfCmd;
// Memory management
typedef std::map<void*, size_t> EMemory;
EMemory _elfMemory;
// Indexes of .shstrtab and .strtab (for convenience)
Elf64_Word _shstrtab_ndx;
Elf64_Word _strtab_ndx;
public:
/*
OclElf object can be created for reading or writing (it could be created for
both reading and writing, which is not supported yet at this time). Currently,
it has two forms:
1) OclElf(eclass, rawElfBytes, rawElfSize, 0, ELF_C_READ)
To load ELF from raw bytes in memory and generate OclElf object. And this
object is for reading only.
2) OclElf(eclass, NULL, 0, elfFileName|NULL, ELF_C_WRITE)
To create an ELF for writing and save it into a file 'elfFileName' (if it
is NULL, the OclElf will create a temporary file and set it to 'elfFileName'.
Since we need to read the ELF into memory, this file 'elfFileName' is created
with both read and write, so that the runtime can use dumpImage() to get ELF
raw bytes by reading this file.
'eclass' is ELF's bitness and it must be the same as the eclass of ELF to
be loaded (for example, rawElfBytes).
Return values of all public APIs with bool return type
true : on success;
false : on error.
*/
OclElf (
unsigned char eclass, // eclass for this ELF
const char* rawElfBytes, // raw ELF bytes to be loaded
uint64_t rawElfSize, // size of the ELF raw bytes
const char* elfFileName, // File to save this ELF.
Elf_Cmd elfcmd // ELF_C_READ/ELF_C_WRITE
);
~OclElf ();
/*
dumpImage() will finalize the ELF and write it into the file. It then reads
it into the memory; and returns it via <buff, len>.
The memory pointed by buff is owned by OclElf object.
*/
bool dumpImage(char** buff, size_t* len);
/*
addSection() is used to create a single ELF section with data <d_buf, d_size>. If
do_copy is true, the OclElf object will make a copy of d_buf and uses that copy to
create an ELF section.
When setting do_copy = false, the caller should make sure that <d_buf, d_size> will
be unchanged and available during the lifetime of this OclElf object; ie before
calling dumpImage().
*/
bool addSection (
oclElfSections id,
const void* d_buf,
size_t d_size,
bool do_copy = true
);
/*
getSection() will return the whole section in <dst, sz>.
The memory pointed by <dst, sz> is owned by the OclElf object.
*/
bool getSection(oclElfSections id, char** dst, size_t* sz) const;
/*
addSymbol() adds a symbol with name 'symbolName' and data <buffer, size>
into the ELF. 'id' indicates which section <buffer, size> will go
into. The meaning of 'do_copy' is the same as addSection().
*/
bool addSymbol(
oclElfSections id, // Section in which symbol is added
const char* symbolName, // Name of symbol
const void* buffer, // Symbol's data
size_t size, // Symbol's size
bool do_copy = true // If true, add a copy of buffer into the section
);
/*
* getSymbol() will return the data associated with
* the symbol from the Elf.
*
* The memory pointed by <buffer, size> is owned by the OclElf object
*/
bool getSymbol(
oclElfSections id, // Section in which symbol is in
const char* symbolName, // Name of the symbol to retrieve
char** buffer, // Symbol's data
size_t* size // Symbol's size
) const;
/*
nextSymbol() and getSymbolInfo() use the symbol handle to access symbols
For example:
for( Sym_Handle s = nextSymbol(NULL); s ; s = nextSymbol(s)) {
SymbolInfo si;
if (!getSymbolInfo(s, &si)) {
Error;
}
use si
}
where nextSymbol(NULL) will return the first symbol.
Note that memory space pointed to by si is owned by OclElf.
*/
bool getSymbolInfo(Sym_Handle sym, SymbolInfo* symInfo) const;
Sym_Handle nextSymbol(Sym_Handle symhandle) const;
/*
Adds a note with name 'noteName' and description "noteDesc"
into the .note section of ELF. Length of note name is 'nameSize'.
Length of note description is "descSize'.
*/
bool addNote(const char* noteName, const char* noteDesc,
size_t nameSize, size_t descSize);
/*
Returns the description of a note whose name is 'noteName'
in 'noteDesc'.
Returns the length of the description in 'descSize'.
*/
bool getNote(const char* noteName, char** noteDesc, size_t *descSize);
/*
Get/set machine and platform (target) for which elf is built.
*/
bool getTarget(uint16_t& machine, oclElfPlatform& platform);
bool setTarget(uint16_t machine, oclElfPlatform platform);
/*
Get/set elf type field from header
*/
bool getType(uint16_t &type);
bool setType(uint16_t type);
/*
Get/set elf flag field from header.
*/
bool getFlags(uint32_t &flag);
bool setFlags(uint32_t flag);
/*
Clear() will return the status of OclElf to just after ctor() is invoked.
However, it will not regenerate a temporary file name like ctor() does.
It is useful when the ELF content needs to be discarded for some reason.
*/
bool Clear();
bool hasError() { return (_err.getOclElfError())[0] != 0; }
const char* getErrMsg() { return _err.getOclElfError(); }
unsigned char getELFClass() { return _eclass; }
bool isHsaCo() const { return (_eclass == ELFCLASS32) ?
(elf32_getehdr(_e)->e_machine == EM_AMDGPU) : (elf64_getehdr(_e)->e_machine == EM_AMDGPU); }
private:
/* Initialization */
bool Init();
/*
Initialize ELF object by creating ELF header and key sections such as
.shstrtab, .strtab, and .symtab.
*/
bool InitElf ();
// Wraper for creating a section header and Elf_Data
bool createShdr (
oclElfSections id,
Elf_Scn*& scn,
Elf64_Word shname,
Elf64_Word shlink = 0
);
Elf_Data* createElfData(
Elf_Scn*& scn,
oclElfSections id,
void* d_buf,
uint64_t d_size,
bool do_copy
);
/*
Create a new section (id) with data <d_buf, d_size>. If do_copy is true,
make a copy of d_buf and create a new section with that copy.
Return the valid Elf_Scn on success; return NULL on error.
Note that newSection() uses Section Header's size, so make sure elf_update()
is invoked properly before invoking newSection().
*/
Elf_Scn* newSection (
oclElfSections id,
const void* d_buf,
size_t d_size,
bool do_copy = true // if true, add a copy of d_buf
);
/*
Add a new data into a section by creating a new data descriptor.
And the new data's offset is returned in 'outOffset'.
*/
bool addSectionData(
Elf64_Xword& outOffset,
oclElfSections id,
const void* buffer,
size_t size,
bool do_copy=true // if true, add a copy of buffer
);
// Return Elf_Data for this section 'id'
bool getSectionData(Elf_Data*& data, oclElfSections id) const;
// Return Elf_Scn for this section 'id'
bool getSectionDesc(Elf_Scn*& scn, oclElfSections id) const;
//
bool getShstrtabNdx(Elf64_Word& outNdx, const char*);
void* oclelf_allocAndCopy(void* p, size_t sz);
void* oclelf_calloc(size_t sz);
void elfMemoryRelease();
};
} // namespace amd
#endif
@@ -0,0 +1,285 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#include "elf_utils.hpp"
#include "memfile.h"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
/*
See elf_utils.hpp for descriptions about each functions
*/
namespace amd {
#define ELF_OPEN mem_open
#define ELF_READ(f, b, l) mem_read((f), (b), (unsigned int)(l))
#define ELF_WRITE mem_write
#define ELF_CLOSE mem_close
#define ELF_LSEEK mem_lseek
/*
Save the error string in _lastErrMsg. If it is built without NDEBUG, the program
will terminate immediately with exit(1).
*/
void OclElfErr::xfail(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vsnprintf(&_lastErrMsg[0], (size_t)MAX_ERROR_MESSAGE_LENGTH, fmt, ap);
va_end(ap);
#ifndef NDEBUG
printf("%s\n", _lastErrMsg);
exit(1);
#endif
}
namespace oclelfutils {
/*
Wrap malloc() with xfail(), so this returns newly-allocated memory or 0.
The memory is guaranteed to be initialized to zero.
*/
void* xmalloc(OclElfErr& err, const size_t len)
{
void *retval = calloc(1, len);
if (retval == NULL) {
err.xfail("xmalloc failed: out of memory");
return NULL;
}
return retval;
}
/*
Return file descriptor on success; return -1 on error and invoke xfail()
to record the error.
*/
int xopen(OclElfErr& err, const char *fname, const int in_flags, const int perms)
{
const int retval = ELF_OPEN(fname, in_flags, perms);
if (retval == -1) {
err.xfail("Failed to open '%s': %s", fname, strerror(errno));
return -1;
}
return retval;
}
/*
Return 0 on success; return -1 on error.
*/
int xclose(OclElfErr& err, const char *fname, const int fd)
{
int rc;
while ( ((rc = :: ELF_CLOSE(fd)) == -1) && (errno == EINTR) ) { ;/* spin. */ }
if (rc == -1) {
err.xfail("Failed to close '%s': %s", fname, strerror(errno));
return -1;
}
return rc;
}
/*
Return the file offset location on success; return -1 on error.
*/
off_t xlseek(
OclElfErr& err,
const char* fname,
const int fd,
const off_t offset,
const int whence)
{
// For really big file _lseeki64/lseek64 are needed. For now,
// lseek/_lseek is enough.
off_t res = ELF_LSEEK(fd, offset, whence);
if (res == -1) {
err.xfail("Failed to seek in '%s': %s", fname, strerror(errno));
return -1;
}
return res;
}
/*
Return the number of bytes that are read on success; return -1 on error.
*/
ssize_t xread(
OclElfErr& err,
const char* fname,
const int fd,
void* buf,
const size_t buf_len
)
{
ssize_t rc;
while (((rc = ELF_READ(fd, buf, buf_len)) == -1) && (errno == EINTR)) { ;/* spin */ }
if (rc < 0) {
err.xfail("Failed to read '%s': %s", fname, strerror(errno));
return -1;
}
return rc;
}
#if 0
/*
Return the number of bytes that have been written on success; return -1 on error.
*/
ssize_t xwrite(OclElfErr& err,
const char* fname,
const int fd,
const void* buf,
const size_t len)
{
ssize_t rc;
while (((rc = ELF_WRITE(fd, buf, len)) == -1) && (errno == EINTR)) { ;/* spin */ }
if ( (rc == -1) || (rc != (ssize_t)len) ) {
err.xfail("Failed to write '%s': %s", fname, strerror(errno));
return -1;
}
return rc;
}
/*
Allocate a copy of (str), invoke xfail() on failure.
Returns NULL on error, or address of the allocated copy
*/
char* xstrdup(OclElfErr& err, const char *str)
{
char* retval = (char*)xmalloc(err, strlen(str) + 1);
if (retval == NULL) {
err.xfail("xstrdup failed: cannot allocate new char string");
return NULL;
}
strcpy(retval, str);
return retval;
}
/*
get the length of an open file in bytes. return -1 on error.
*/
uint64_t xget_file_size(OclElfErr& err, const char *fname, const int fd)
{
struct stat statbuf;
if (fstat(fd, &statbuf) == -1) {
err.xfail("Failed to fstat '%s': %s", fname, strerror(errno));
return -1;
}
return (uint64_t) statbuf.st_size;
}
/*
Copy file 'infd' to file 'outfd'.
Return the total number of bytes copied on success; return -1 on error.
*/
int64_t xcopyfile(
OclElfErr& err,
const char* in,
const int infd,
const char* out,
const int outfd
)
{
uint64_t retval = 0;
ssize_t rc = 0;
off_t res = xlseek(err, in, infd, 0, SEEK_SET);
if (res == -1) {
err.xfail("xcopyfile failed in xlseek : in %s, out %s", in, out);
return -1;
}
uint8_t* copybuf = err._copyBuffer;
if (copybuf == NULL) {
copybuf = (uint8_t*)xmalloc(err, IO_BUF_SIZE);
err._copyBuffer = copybuf;
}
while ( (rc = xread(err, in, infd, copybuf, IO_BUF_SIZE)) > 0 ) {
retval += (uint64_t) rc;
int ret = xwrite(err, out, outfd, copybuf, rc);
if (ret == -1) {
err.xfail("xcopyfile failed in xwrite: in %s, out %s", in, out);
return -1;
}
}
if (rc == -1) {
err.xfail("xcopyfile failed in xread: in %s, out %s", in, out);
return -1;
}
return retval;
}
/*
Copy file from 'infd' to current offset in 'outfd', for 'size' bytes.
Return 'size' on success; return -1 on error.
*/
int64_t
xcopyfile_range(
OclElfErr& err, const char *in, const int infd,
const char *out, const int outfd,
const uint64_t offset, const uint64_t size
)
{
uint8_t* copybuf = err._copyBuffer;
if (copybuf == NULL) {
copybuf = (uint8_t*)xmalloc(err, IO_BUF_SIZE);
err._copyBuffer = copybuf;
}
ssize_t rc = xlseek(err, in, infd, (off_t) offset, SEEK_SET);
if (rc == -1) {
err.xfail("xcopyfile_range: xlseek() failed: %s", in);
return -1;
}
uint64_t remaining = size;
while (remaining >= IO_BUF_SIZE) {
rc = xread(err, in, infd, copybuf, IO_BUF_SIZE);
if ((rc == -1) || (rc != IO_BUF_SIZE)) {
err.xfail("xcopyfile_range: xread() failed %s", in);
return -1;
}
rc = xwrite(err, out, outfd, copybuf, IO_BUF_SIZE);
if (rc == -1) {
err.xfail("xcopyfile_range: xwrite() failed: %s", out);
}
remaining -= (uint64_t) IO_BUF_SIZE;
}
if (remaining > 0) {
rc = xread(err, in, infd, copybuf, IO_BUF_SIZE);
if ((rc == -1) || (rc != (ssize_t)remaining)) {
err.xfail("xcopyfile_range: xread() failed %s", in);
return -1;
}
rc = xwrite(err, out, outfd, copybuf, rc);
if (rc == -1) {
err.xfail("xcopyfile_range: xwrite() failed: %s", out);
}
}
return size;
}
uint64_t
align_to_page(const uint64_t offset)
{
// TODO_jugu don't use hardcoded pagesize.
return (offset + ((1LL << 12) -1)) & ((uint64_t)(-(1LL << 12)));
}
#endif
} // namespace elfutils
} // namespace amd
@@ -0,0 +1,150 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ELF_UTILS_HPP
#define _ELF_UTILS_HPP
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "top.hpp"
namespace amd {
#define MAX_ERROR_MESSAGE_LENGTH 1024
#define IO_BUF_SIZE 16 * 1024
class OclElfErr
{
public:
// Temperary buffer for copying from file to file
uint8_t* _copyBuffer; // Initialized first time it is used
private:
// Keep the last error message.
char _lastErrMsg[MAX_ERROR_MESSAGE_LENGTH];
public:
OclElfErr() : _copyBuffer(NULL) { _lastErrMsg[0] = 0; }
~OclElfErr() {
if (_copyBuffer) {
free(_copyBuffer);
}
}
void Init() { _lastErrMsg[0] = 0; }
void Fini() {
_lastErrMsg[0] = 0;
if (_copyBuffer) {
free(_copyBuffer);
}
_copyBuffer = NULL;
}
// Return the last error message.
const char* getOclElfError() const { return _lastErrMsg; }
//
// Save the error string in ErrorMessage. If it is built without NDEBUG, the program
// will terminate immediately with exit(1).
//
void xfail(const char *fmt, ...);
};
namespace oclelfutils {
/*
Wrap malloc() with xfail(), so this returns newly-allocated memory or 0.
The memory is guaranteed to be initialized to zero.
*/
void* xmalloc(OclElfErr& err, const size_t len);
/*
Return file descriptor on success; return -1 on error and invoke xfail()
to record the error.
*/
int xopen(OclElfErr& err, const char *fname, const int flags, const int perms);
/*
Return 0 on success; return -1 on error.
*/
int xclose(OclElfErr& err, const char *fname, const int fd);
/*
Return the file offset location on success; return -1 on error.
*/
off_t xlseek(OclElfErr& err, const char *fname, const int fd,
const off_t o, const int whence);
/*
Return the number of bytes that are read on success; return -1 on error.
*/
ssize_t xread(
OclElfErr& err,
const char* fname, // File name for file descriptor 'fd'
const int fd, // File descriptor
void* buf, // buffer for reading
const size_t buf_len // capacity of buffer in bytes
);
#if 0
/*
Return the number of bytes that have been written on success; return -1 on error.
*/
ssize_t xwrite(
OclElfErr& err,
const char* fname, // File name for file descriptor 'fd'
const int fd, // File descriptor
const void* buf, // data buffer to be written out
const size_t buf_len // the size of data in bytes
);
/*
Allocate a copy of (str), invoke xfail() on failure.
Returns 0 on error, or address of the allocated copy
*/
char* xstrdup(OclElfErr& err, const char *str);
/*
get the length of an open file in bytes. return -1 if error.
*/
uint64_t xget_file_size(OclElfErr& err, const char *fname, const int fd);
/*
Copy file 'infd' to file 'outfd'.
Return the total number of bytes copied on success; return -1 on error.
*/
int64_t xcopyfile(OclElfErr& err, const char *in, const int infd,
const char *out, const int outfd);
/*
Copy file from 'infd' to current offset in 'outfd', for 'size' bytes.
Return 'size' on success; return -1 on error.
*/
int64_t xcopyfile_range(OclElfErr& err, const char *in, const int infd,
const char *out, const int outfd,
const uint64_t offset, const uint64_t size);
// Align a value to the page size.
uint64_t align_to_page(const uint64_t offset);
#endif
} // namespace elfutils
} // namespace amd
#endif
@@ -0,0 +1,12 @@
##
########################################################################################################################
#
# Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
#
########################################################################################################################
cmake_minimum_required(VERSION 3.10)
if(NOT TARGET oclelf)
add_subdirectory(libelf)
endif()
@@ -0,0 +1,539 @@
/*-
* 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 2064 2011-10-26 15:12:32Z jkoshy $
*/
/**
** Miscellanous definitions needed by multiple components.
**/
#ifndef _ELFTC_H
#define _ELFTC_H
#ifndef NULL
#define NULL ((void *) 0)
#endif
#ifndef offsetof
// change from (int) to (char *) for x64 gcc
#define offsetof(T, M) ((char *) &((T*) 0) -> M)
#endif
/*
* Supply macros missing from <sys/queue.h>
*/
#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_LAST
#define STAILQ_LAST(head, type, field) \
(STAILQ_EMPTY((head)) ? \
NULL : \
((struct type *)(void *) \
((char *)((head)->stqh_last) - offsetof(struct type, field))))
#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
/*
* Symbols that are sometimes missing in system headers.
*/
#ifndef DT_DEPRECATED_SPARC_REGISTER
#define DT_DEPRECATED_SPARC_REGISTER 0x70000001
#endif
#ifndef DT_GNU_PRELINKED
#define DT_GNU_PRELINKED 0x6FFFFDF5U
#endif
#ifndef DT_GNU_CONFLICTSZ
#define DT_GNU_CONFLICTSZ 0x6FFFFDF6U
#endif
#ifndef DT_GNU_LIBLISTSZ
#define DT_GNU_LIBLISTSZ 0x6FFFFDF7U
#endif
#ifndef DT_GNU_HASH
#define DT_GNU_HASH 0x6FFFFEF5U
#endif
#ifndef DT_GNU_CONFLICT
#define DT_GNU_CONFLICT 0x6FFFFEF8U
#endif
#ifndef DT_GNU_LIBLIST
#define DT_GNU_LIBLIST 0x6FFFFEF9U
#endif
#ifndef DT_MAXPOSTAGS
#define DT_MAXPOSTAGS 34
#endif
#ifndef DT_SUNW_AUXILIARY
#define DT_SUNW_AUXILIARY 0x6000000D
#endif
#ifndef DT_SUNW_CAP
#define DT_SUNW_CAP 0x60000010
#endif
#ifndef DT_SUNW_FILTER
#define DT_SUNW_FILTER 0x6000000F
#endif
#ifndef DT_SUNW_RTLDINF
#define DT_SUNW_RTLDINF 0x6000000E
#endif
#ifndef DT_USED
#define DT_USED 0x7FFFFFFE
#endif
#ifndef ELFOSABI_86OPEN
#define ELFOSABI_86OPEN 5
#endif
#ifndef ELFOSABI_AIX
#define ELFOSABI_AIX 7
#endif
#ifndef ELFOSABI_HURD
#define ELFOSABI_HURD 4
#endif
#ifndef ELFOSABI_NONE
#define ELFOSABI_NONE 0
#endif
#ifndef ELFOSABI_NSK
#define ELFOSABI_NSK 14
#endif
#ifndef ELFOSABI_OPENVMS
#define ELFOSABI_OPENVMS 13
#endif
/*
* Supply missing EM_XXX definitions.
*/
#ifndef EM_68HC05
#define EM_68HC05 72
#endif
#ifndef EM_68HC08
#define EM_68HC08 71
#endif
#ifndef EM_68HC11
#define EM_68HC11 70
#endif
#ifndef EM_68HC16
#define EM_68HC16 69
#endif
#ifndef EM_ARCA
#define EM_ARCA 109
#endif
#ifndef EM_ARC_A5
#define EM_ARC_A5 93
#endif
#ifndef EM_AVR
#define EM_AVR 83
#endif
#ifndef EM_BLACKFIN
#define EM_BLACKFIN 106
#endif
#ifndef EM_CR
#define EM_CR 103
#endif
#ifndef EM_CRIS
#define EM_CRIS 76
#endif
#ifndef EM_D10V
#define EM_D10V 85
#endif
#ifndef EM_D30V
#define EM_D30V 86
#endif
#ifndef EM_F2MC16
#define EM_F2MC16 104
#endif
#ifndef EM_FIREPATH
#define EM_FIREPATH 78
#endif
#ifndef EM_FR30
#define EM_FR30 84
#endif
#ifndef EM_FX66
#define EM_FX66 66
#endif
#ifndef EM_HUANY
#define EM_HUANY 81
#endif
#ifndef EM_IP2K
#define EM_IP2K 101
#endif
#ifndef EM_JAVELIN
#define EM_JAVELIN 77
#endif
#ifndef EM_M32R
#define EM_M32R 88
#endif
#ifndef EM_MAX
#define EM_MAX 102
#endif
#ifndef EM_MMIX
#define EM_MMIX 80
#endif
#ifndef EM_MN10200
#define EM_MN10200 90
#endif
#ifndef EM_MN10300
#define EM_MN10300 89
#endif
#ifndef EM_MSP430
#define EM_MSP430 105
#endif
#ifndef EM_NS32K
#define EM_NS32K 97
#endif
#ifndef EM_OPENRISC
#define EM_OPENRISC 92
#endif
#ifndef EM_PDSP
#define EM_PDSP 63
#endif
#ifndef EM_PJ
#define EM_PJ 91
#endif
#ifndef EM_PRISM
#define EM_PRISM 82
#endif
#ifndef EM_SEP
#define EM_SEP 108
#endif
#ifndef EM_SE_C33
#define EM_SE_C33 107
#endif
#ifndef EM_SNP1K
#define EM_SNP1K 99
#endif
#ifndef EM_ST19
#define EM_ST19 74
#endif
#ifndef EM_ST200
#define EM_ST200 100
#endif
#ifndef EM_ST7
#define EM_ST7 68
#endif
#ifndef EM_ST9PLUS
#define EM_ST9PLUS 67
#endif
#ifndef EM_SVX
#define EM_SVX 73
#endif
#ifndef EM_TMM_GPP
#define EM_TMM_GPP 96
#endif
#ifndef EM_TPC
#define EM_TPC 98
#endif
#ifndef EM_UNICORE
#define EM_UNICORE 110
#endif
#ifndef EM_V850
#define EM_V850 87
#endif
#ifndef EM_VAX
#define EM_VAX 75
#endif
#ifndef EM_VIDEOCORE
#define EM_VIDEOCORE 95
#endif
#ifndef EM_XTENSA
#define EM_XTENSA 94
#endif
#ifndef EM_ZSP
#define EM_ZSP 79
#endif
#ifndef PN_XNUM
#define PN_XNUM 0xFFFFU
#endif
#ifndef R_IA_64_DIR32LSB
#define R_IA_64_DIR32LSB 0x25
#endif
#ifndef R_IA_64_DIR64LSB
#define R_IA_64_DIR64LSB 0x27
#endif
#ifndef R_IA_64_SECREL32LSB
#define R_IA_64_SECREL32LSB 0x65
#endif
#ifndef R_MIPS_32
#define R_MIPS_32 0x2
#endif
#ifndef R_PPC_ADDR32
#define R_PPC_ADDR32 0x1
#endif
#ifndef R_SPARC_UA32
#define R_SPARC_UA32 23
#endif
#ifndef R_SPARC_UA64
#define R_SPARC_UA64 54
#endif
#ifndef R_X86_64_32
#define R_X86_64_32 10
#endif
#ifndef R_X86_64_64
#define R_X86_64_64 1
#endif
#ifndef SHT_AMD64_UNWIND
#define SHT_AMD64_UNWIND 0x70000001
#endif
#ifndef SHT_SUNW_ANNOTATE
#define SHT_SUNW_ANNOTATE 0X6FFFFFF7
#endif
#ifndef SHT_SUNW_DEBUGSTR
#define SHT_SUNW_DEBUGSTR 0X6FFFFFF8
#endif
#ifndef SHT_SUNW_DEBUG
#define SHT_SUNW_DEBUG 0X6FFFFFF9
#endif
#ifndef SHT_SUNW_cap
#define SHT_SUNW_cap 0x6FFFFFF5
#endif
#ifndef SHT_SUNW_dof
#define SHT_SUNW_dof 0x6FFFFFF4
#endif
#ifndef SHT_SUNW_verdef
#define SHT_SUNW_verdef 0x6FFFFFFD
#endif
#ifndef SHT_SUNW_verneed
#define SHT_SUNW_verneed 0x6FFFFFFE
#endif
#ifndef SHT_SUNW_versym
#define SHT_SUNW_versym 0x6FFFFFFF
#endif
#ifndef SHN_XINDEX
#define SHN_XINDEX 0xFFFFU
#endif
#ifndef SHT_GNU_ATTRIBUTES
#define SHT_GNU_ATTRIBUTES 0x6FFFFFF5U
#endif
#ifndef SHT_GNU_HASH
#define SHT_GNU_HASH 0x6FFFFFF6U
#endif
#ifndef SHT_GNU_LIBLIST
#define SHT_GNU_LIBLIST 0x6FFFFFF7U
#endif
/*
* VCS Ids.
*/
#ifndef ELFTC_VCSID
#if defined(__FreeBSD__)
#define ELFTC_VCSID(ID) __FBSDID(ID)
#endif
#if defined(__linux__) || defined(__GNU__) || defined(__GLIBC__)
#if defined(__GNUC__)
#define ELFTC_VCSID(ID) __asm__(".ident\t\"" ID "\"")
#else
#define ELFTC_VCSID(ID) /**/
#endif
#endif
#if defined(__NetBSD__)
#define ELFTC_VCSID(ID) __RCSID(ID)
#endif
#endif /* ELFTC_VCSID */
/*
* Provide an equivalent for getprogname(3).
*/
#ifndef ELFTC_GETPROGNAME
#if defined(__FreeBSD__) || defined(__NetBSD__)
#include <stdlib.h>
#define ELFTC_GETPROGNAME() getprogname()
#endif /* defined(__FreeBSD__) || defined(__NetBSD__) */
#if defined(__linux__)
#ifdef __cplusplus
extern "C" {
#endif
/*
* GLIBC based systems have a global 'char *' pointer referencing
* the executable's name.
*/
extern /*const*/ char *program_invocation_short_name;
#ifdef __cplusplus
}
#endif
#define ELFTC_GETPROGNAME() program_invocation_short_name
#endif /* __linux__ */
#endif /* ELFTC_GETPROGNAME */
/**
** Per-OS configuration.
**/
#if defined(__linux__)
#include <endian.h>
#define ELFTC_BYTE_ORDER __BYTE_ORDER
#define ELFTC_BYTE_ORDER_LITTLE_ENDIAN __LITTLE_ENDIAN
#define ELFTC_BYTE_ORDER_BIG_ENDIAN __BIG_ENDIAN
/*
* Debian GNU/Linux is missing 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 /* __linux__ */
#if defined(__FreeBSD__)
#include <osreldate.h>
#include <sys/endian.h>
#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_STRMODE 1
#if __FreeBSD_version <= 900000
#define ELFTC_BROKEN_YY_NO_INPUT 1
#endif
#endif /* __FreeBSD__ */
#if defined(__NetBSD__)
#include <sys/endian.h>
#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_STRMODE 1
#define ELFTC_BROKEN_YY_NO_INPUT 1
#endif /* __NetBSD __ */
#endif /* _ELFTC_H */
@@ -0,0 +1,47 @@
#!/bin/sh
#
# $Id: native-elf-format 2064 2011-10-26 15:12:32Z jkoshy $
#
# 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 '
$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);
}'
@@ -0,0 +1,14 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#if !defined(_LP64)
#define ELFTC_CLASS ELFCLASS32
#else
#define ELFTC_CLASS ELFCLASS64
#endif
#define ELFTC_ARCH EM_386
#define ELFTC_BYTEORDER ELFDATA2LSB
@@ -0,0 +1,906 @@
/*
Copyright (c) 2003-2011, Troy D. Hanson http://uthash.sourceforge.net
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER
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: uthash.h 2064 2011-10-26 15:12:32Z jkoshy $ */
#ifndef UTHASH_H
#define UTHASH_H
#include <string.h> /* memcmp,strlen */
#include <stddef.h> /* ptrdiff_t */
#include <stdlib.h> /* exit() */
/* These macros use decltype or the earlier __typeof GNU extension.
As decltype is only available in newer compilers (VS2010 or gcc 4.3+
when compiling c++ source) this code uses whatever method is needed
or, for VS2008 where neither is available, uses casting workarounds. */
#ifdef _MSC_VER /* MS compiler */
#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
#define DECLTYPE(x) (decltype(x))
#else /* VS2008 or older (or VS2010 in C mode) */
#define NO_DECLTYPE
#define DECLTYPE(x)
#endif
#else /* GNU, Sun and other compilers */
#define DECLTYPE(x) (__typeof(x))
#endif
#ifdef NO_DECLTYPE
#define DECLTYPE_ASSIGN(dst,src) \
do { \
char **_da_dst = (char**)(&(dst)); \
*_da_dst = (char*)(src); \
} while(0)
#else
#define DECLTYPE_ASSIGN(dst,src) \
do { \
(dst) = DECLTYPE(dst)(src); \
} while(0)
#endif
/* a number of the hash function use uint32_t which isn't defined on win32 */
#ifdef _MSC_VER
typedef unsigned int uint32_t;
typedef unsigned char uint8_t;
#else
#include <inttypes.h> /* uint32_t */
#endif
#define UTHASH_VERSION 1.9.4
#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
#define uthash_free(ptr,sz) free(ptr) /* free fcn */
#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
#define uthash_expand_fyi(tbl) /* can be defined to log expands */
/* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
/* calculate the element whose hash handle address is hhe */
#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
#define HASH_FIND(hh,head,keyptr,keylen,out) \
do { \
unsigned _hf_bkt,_hf_hashv; \
out=NULL; \
if (head) { \
HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
keyptr,keylen,out); \
} \
} \
} while (0)
#ifdef HASH_BLOOM
#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
#define HASH_BLOOM_MAKE(tbl) \
do { \
(tbl)->bloom_nbits = HASH_BLOOM; \
(tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
(tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
} while (0);
#define HASH_BLOOM_FREE(tbl) \
do { \
uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
} while (0);
#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
#define HASH_BLOOM_ADD(tbl,hashv) \
HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#define HASH_BLOOM_TEST(tbl,hashv) \
HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
#else
#define HASH_BLOOM_MAKE(tbl)
#define HASH_BLOOM_FREE(tbl)
#define HASH_BLOOM_ADD(tbl,hashv)
#define HASH_BLOOM_TEST(tbl,hashv) (1)
#endif
#define HASH_MAKE_TABLE(hh,head) \
do { \
(head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
sizeof(UT_hash_table)); \
if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
(head)->hh.tbl->tail = &((head)->hh); \
(head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
(head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
(head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
(head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
memset((head)->hh.tbl->buckets, 0, \
HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
HASH_BLOOM_MAKE((head)->hh.tbl); \
(head)->hh.tbl->signature = HASH_SIGNATURE; \
} while(0)
#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
do { \
unsigned _ha_bkt; \
(add)->hh.next = NULL; \
(add)->hh.key = (char*)keyptr; \
(add)->hh.keylen = keylen_in; \
if (!(head)) { \
head = (add); \
(head)->hh.prev = NULL; \
HASH_MAKE_TABLE(hh,head); \
} else { \
(head)->hh.tbl->tail->next = (add); \
(add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
(head)->hh.tbl->tail = &((add)->hh); \
} \
(head)->hh.tbl->num_items++; \
(add)->hh.tbl = (head)->hh.tbl; \
HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
(add)->hh.hashv, _ha_bkt); \
HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
HASH_FSCK(hh,head); \
} while(0)
#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
do { \
bkt = ((hashv) & ((num_bkts) - 1)); \
} while(0)
/* delete "delptr" from the hash table.
* "the usual" patch-up process for the app-order doubly-linked-list.
* The use of _hd_hh_del below deserves special explanation.
* These used to be expressed using (delptr) but that led to a bug
* if someone used the same symbol for the head and deletee, like
* HASH_DELETE(hh,users,users);
* We want that to work, but by changing the head (users) below
* we were forfeiting our ability to further refer to the deletee (users)
* in the patch-up process. Solution: use scratch space to
* copy the deletee pointer, then the latter references are via that
* scratch pointer rather than through the repointed (users) symbol.
*/
#define HASH_DELETE(hh,head,delptr) \
do { \
unsigned _hd_bkt; \
struct UT_hash_handle *_hd_hh_del; \
if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
HASH_BLOOM_FREE((head)->hh.tbl); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
head = NULL; \
} else { \
_hd_hh_del = &((delptr)->hh); \
if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
(head)->hh.tbl->tail = \
(UT_hash_handle*)((char*)((delptr)->hh.prev) + \
(head)->hh.tbl->hho); \
} \
if ((delptr)->hh.prev) { \
((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
(head)->hh.tbl->hho))->next = (delptr)->hh.next; \
} else { \
DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
} \
if (_hd_hh_del->next) { \
((UT_hash_handle*)((char*)_hd_hh_del->next + \
(head)->hh.tbl->hho))->prev = \
_hd_hh_del->prev; \
} \
HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
(head)->hh.tbl->num_items--; \
} \
HASH_FSCK(hh,head); \
} while (0)
/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
#define HASH_FIND_STR(head,findstr,out) \
HASH_FIND(hh,head,findstr,strlen(findstr),out)
#define HASH_ADD_STR(head,strfield,add) \
HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
#define HASH_FIND_INT(head,findint,out) \
HASH_FIND(hh,head,findint,sizeof(int),out)
#define HASH_ADD_INT(head,intfield,add) \
HASH_ADD(hh,head,intfield,sizeof(int),add)
#define HASH_FIND_PTR(head,findptr,out) \
HASH_FIND(hh,head,findptr,sizeof(void *),out)
#define HASH_ADD_PTR(head,ptrfield,add) \
HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
#define HASH_DEL(head,delptr) \
HASH_DELETE(hh,head,delptr)
/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
* This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
*/
#ifdef HASH_DEBUG
#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
#define HASH_FSCK(hh,head) \
do { \
unsigned _bkt_i; \
unsigned _count, _bkt_count; \
char *_prev; \
struct UT_hash_handle *_thh; \
if (head) { \
_count = 0; \
for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
_bkt_count = 0; \
_thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
_prev = NULL; \
while (_thh) { \
if (_prev != (char*)(_thh->hh_prev)) { \
HASH_OOPS("invalid hh_prev %p, actual %p\n", \
_thh->hh_prev, _prev ); \
} \
_bkt_count++; \
_prev = (char*)(_thh); \
_thh = _thh->hh_next; \
} \
_count += _bkt_count; \
if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
HASH_OOPS("invalid bucket count %d, actual %d\n", \
(head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
} \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid hh item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
/* traverse hh in app order; check next/prev integrity, count */ \
_count = 0; \
_prev = NULL; \
_thh = &(head)->hh; \
while (_thh) { \
_count++; \
if (_prev !=(char*)(_thh->prev)) { \
HASH_OOPS("invalid prev %p, actual %p\n", \
_thh->prev, _prev ); \
} \
_prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
_thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
(head)->hh.tbl->hho) : NULL ); \
} \
if (_count != (head)->hh.tbl->num_items) { \
HASH_OOPS("invalid app item count %d, actual %d\n", \
(head)->hh.tbl->num_items, _count ); \
} \
} \
} while (0)
#else
#define HASH_FSCK(hh,head)
#endif
/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
* the descriptor to which this macro is defined for tuning the hash function.
* The app can #include <unistd.h> to get the prototype for write(2). */
#ifdef HASH_EMIT_KEYS
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
do { \
unsigned _klen = fieldlen; \
write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
write(HASH_EMIT_KEYS, keyptr, fieldlen); \
} while (0)
#else
#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
#endif
/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
#ifdef HASH_FUNCTION
#define HASH_FCN HASH_FUNCTION
#else
#define HASH_FCN HASH_JEN
#endif
/* The Bernstein hash function, used in Perl prior to v5.6 */
#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hb_keylen=keylen; \
char *_hb_key=(char*)(key); \
(hashv) = 0; \
while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
bkt = (hashv) & (num_bkts-1); \
} while (0)
/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
* http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _sx_i; \
char *_hs_key=(char*)(key); \
hashv = 0; \
for(_sx_i=0; _sx_i < keylen; _sx_i++) \
hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
bkt = hashv & (num_bkts-1); \
} while (0)
#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _fn_i; \
char *_hf_key=(char*)(key); \
hashv = 2166136261UL; \
for(_fn_i=0; _fn_i < keylen; _fn_i++) \
hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
bkt = hashv & (num_bkts-1); \
} while(0);
#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _ho_i; \
char *_ho_key=(char*)(key); \
hashv = 0; \
for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
hashv += _ho_key[_ho_i]; \
hashv += (hashv << 10); \
hashv ^= (hashv >> 6); \
} \
hashv += (hashv << 3); \
hashv ^= (hashv >> 11); \
hashv += (hashv << 15); \
bkt = hashv & (num_bkts-1); \
} while(0)
#define HASH_JEN_MIX(a,b,c) \
do { \
a -= b; a -= c; a ^= ( c >> 13 ); \
b -= c; b -= a; b ^= ( a << 8 ); \
c -= a; c -= b; c ^= ( b >> 13 ); \
a -= b; a -= c; a ^= ( c >> 12 ); \
b -= c; b -= a; b ^= ( a << 16 ); \
c -= a; c -= b; c ^= ( b >> 5 ); \
a -= b; a -= c; a ^= ( c >> 3 ); \
b -= c; b -= a; b ^= ( a << 10 ); \
c -= a; c -= b; c ^= ( b >> 15 ); \
} while (0)
#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
do { \
unsigned _hj_i,_hj_j,_hj_k; \
char *_hj_key=(char*)(key); \
hashv = 0xfeedbeef; \
_hj_i = _hj_j = 0x9e3779b9; \
_hj_k = keylen; \
while (_hj_k >= 12) { \
_hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ ( (unsigned)_hj_key[2] << 16 ) \
+ ( (unsigned)_hj_key[3] << 24 ) ); \
_hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ ( (unsigned)_hj_key[6] << 16 ) \
+ ( (unsigned)_hj_key[7] << 24 ) ); \
hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ ( (unsigned)_hj_key[10] << 16 ) \
+ ( (unsigned)_hj_key[11] << 24 ) ); \
\
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
\
_hj_key += 12; \
_hj_k -= 12; \
} \
hashv += keylen; \
switch ( _hj_k ) { \
case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
case 5: _hj_j += _hj_key[4]; \
case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
case 1: _hj_i += _hj_key[0]; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
bkt = hashv & (num_bkts-1); \
} while(0)
/* The Paul Hsieh hash function */
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
#define get16bits(d) (*((const uint16_t *) (d)))
#endif
#if !defined (get16bits)
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+(uint32_t)(((const uint8_t *)(d))[0]) )
#endif
#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
do { \
char *_sfh_key=(char*)(key); \
uint32_t _sfh_tmp, _sfh_len = keylen; \
\
int _sfh_rem = _sfh_len & 3; \
_sfh_len >>= 2; \
hashv = 0xcafebabe; \
\
/* Main loop */ \
for (;_sfh_len > 0; _sfh_len--) { \
hashv += get16bits (_sfh_key); \
_sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
hashv = (hashv << 16) ^ _sfh_tmp; \
_sfh_key += 2*sizeof (uint16_t); \
hashv += hashv >> 11; \
} \
\
/* Handle end cases */ \
switch (_sfh_rem) { \
case 3: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 16; \
hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
hashv += hashv >> 11; \
break; \
case 2: hashv += get16bits (_sfh_key); \
hashv ^= hashv << 11; \
hashv += hashv >> 17; \
break; \
case 1: hashv += *_sfh_key; \
hashv ^= hashv << 10; \
hashv += hashv >> 1; \
} \
\
/* Force "avalanching" of final 127 bits */ \
hashv ^= hashv << 3; \
hashv += hashv >> 5; \
hashv ^= hashv << 4; \
hashv += hashv >> 17; \
hashv ^= hashv << 25; \
hashv += hashv >> 6; \
bkt = hashv & (num_bkts-1); \
} while(0);
#ifdef HASH_USING_NO_STRICT_ALIASING
/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
* For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
* MurmurHash uses the faster approach only on CPU's where we know it's safe.
*
* Note the preprocessor built-in defines can be emitted using:
*
* gcc -m64 -dM -E - < /dev/null (on gcc)
* cc -## a.c (where a.c is a simple test file) (Sun Studio)
*/
#if (defined(__i386__) || defined(__x86_64__))
#define MUR_GETBLOCK(p,i) p[i]
#else /* non intel */
#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >> 8))
#else /* assume little endian non-intel */
#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
#define MUR_TWO_TWO(p) ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) << 8))
#endif
#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) : \
(MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
(MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) : \
MUR_ONE_THREE(p))))
#endif
#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
#define MUR_FMIX(_h) \
do { \
_h ^= _h >> 16; \
_h *= 0x85ebca6b; \
_h ^= _h >> 13; \
_h *= 0xc2b2ae35l; \
_h ^= _h >> 16; \
} while(0)
#define HASH_MUR(key,keylen,num_bkts,hashv,bkt) \
do { \
const uint8_t *_mur_data = (const uint8_t*)(key); \
const int _mur_nblocks = (keylen) / 4; \
uint32_t _mur_h1 = 0xf88D5353; \
uint32_t _mur_c1 = 0xcc9e2d51; \
uint32_t _mur_c2 = 0x1b873593; \
const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
int _mur_i; \
for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) { \
uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i); \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
\
_mur_h1 ^= _mur_k1; \
_mur_h1 = MUR_ROTL32(_mur_h1,13); \
_mur_h1 = _mur_h1*5+0xe6546b64; \
} \
const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
uint32_t _mur_k1=0; \
switch((keylen) & 3) { \
case 3: _mur_k1 ^= _mur_tail[2] << 16; \
case 2: _mur_k1 ^= _mur_tail[1] << 8; \
case 1: _mur_k1 ^= _mur_tail[0]; \
_mur_k1 *= _mur_c1; \
_mur_k1 = MUR_ROTL32(_mur_k1,15); \
_mur_k1 *= _mur_c2; \
_mur_h1 ^= _mur_k1; \
} \
_mur_h1 ^= (keylen); \
MUR_FMIX(_mur_h1); \
hashv = _mur_h1; \
bkt = hashv & (num_bkts-1); \
} while(0)
#endif /* HASH_USING_NO_STRICT_ALIASING */
/* key comparison function; return 0 if keys equal */
#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
/* iterate over items in a known bucket to find desired item */
#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
do { \
if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
else out=NULL; \
while (out) { \
if (out->hh.keylen == keylen_in) { \
if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
} \
if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
else out = NULL; \
} \
} while(0)
/* add an item to a bucket */
#define HASH_ADD_TO_BKT(head,addhh) \
do { \
head.count++; \
(addhh)->hh_next = head.hh_head; \
(addhh)->hh_prev = NULL; \
if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
(head).hh_head=addhh; \
if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
&& (addhh)->tbl->noexpand != 1) { \
HASH_EXPAND_BUCKETS((addhh)->tbl); \
} \
} while(0)
/* remove an item from a given bucket */
#define HASH_DEL_IN_BKT(hh,head,hh_del) \
(head).count--; \
if ((head).hh_head == hh_del) { \
(head).hh_head = hh_del->hh_next; \
} \
if (hh_del->hh_prev) { \
hh_del->hh_prev->hh_next = hh_del->hh_next; \
} \
if (hh_del->hh_next) { \
hh_del->hh_next->hh_prev = hh_del->hh_prev; \
}
/* Bucket expansion has the effect of doubling the number of buckets
* and redistributing the items into the new buckets. Ideally the
* items will distribute more or less evenly into the new buckets
* (the extent to which this is true is a measure of the quality of
* the hash function as it applies to the key domain).
*
* With the items distributed into more buckets, the chain length
* (item count) in each bucket is reduced. Thus by expanding buckets
* the hash keeps a bound on the chain length. This bounded chain
* length is the essence of how a hash provides constant time lookup.
*
* The calculation of tbl->ideal_chain_maxlen below deserves some
* explanation. First, keep in mind that we're calculating the ideal
* maximum chain length based on the *new* (doubled) bucket count.
* In fractions this is just n/b (n=number of items,b=new num buckets).
* Since the ideal chain length is an integer, we want to calculate
* ceil(n/b). We don't depend on floating point arithmetic in this
* hash, so to calculate ceil(n/b) with integers we could write
*
* ceil(n/b) = (n/b) + ((n%b)?1:0)
*
* and in fact a previous version of this hash did just that.
* But now we have improved things a bit by recognizing that b is
* always a power of two. We keep its base 2 log handy (call it lb),
* so now we can write this with a bit shift and logical AND:
*
* ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
*
*/
#define HASH_EXPAND_BUCKETS(tbl) \
do { \
unsigned _he_bkt; \
unsigned _he_bkt_i; \
struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
_he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
memset(_he_new_buckets, 0, \
2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
tbl->ideal_chain_maxlen = \
(tbl->num_items >> (tbl->log2_num_buckets+1)) + \
((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
tbl->nonideal_items = 0; \
for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
{ \
_he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
while (_he_thh) { \
_he_hh_nxt = _he_thh->hh_next; \
HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
_he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
tbl->nonideal_items++; \
_he_newbkt->expand_mult = _he_newbkt->count / \
tbl->ideal_chain_maxlen; \
} \
_he_thh->hh_prev = NULL; \
_he_thh->hh_next = _he_newbkt->hh_head; \
if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
_he_thh; \
_he_newbkt->hh_head = _he_thh; \
_he_thh = _he_hh_nxt; \
} \
} \
uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
tbl->num_buckets *= 2; \
tbl->log2_num_buckets++; \
tbl->buckets = _he_new_buckets; \
tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
(tbl->ineff_expands+1) : 0; \
if (tbl->ineff_expands > 1) { \
tbl->noexpand=1; \
uthash_noexpand_fyi(tbl); \
} \
uthash_expand_fyi(tbl); \
} while(0)
/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
/* Note that HASH_SORT assumes the hash handle name to be hh.
* HASH_SRT was added to allow the hash handle name to be passed in. */
#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
#define HASH_SRT(hh,head,cmpfcn) \
do { \
unsigned _hs_i; \
unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
if (head) { \
_hs_insize = 1; \
_hs_looping = 1; \
_hs_list = &((head)->hh); \
while (_hs_looping) { \
_hs_p = _hs_list; \
_hs_list = NULL; \
_hs_tail = NULL; \
_hs_nmerges = 0; \
while (_hs_p) { \
_hs_nmerges++; \
_hs_q = _hs_p; \
_hs_psize = 0; \
for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
_hs_psize++; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
if (! (_hs_q) ) break; \
} \
_hs_qsize = _hs_insize; \
while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
if (_hs_psize == 0) { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else if (( \
cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
) <= 0) { \
_hs_e = _hs_p; \
_hs_p = (UT_hash_handle*)((_hs_p->next) ? \
((void*)((char*)(_hs_p->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_psize--; \
} else { \
_hs_e = _hs_q; \
_hs_q = (UT_hash_handle*)((_hs_q->next) ? \
((void*)((char*)(_hs_q->next) + \
(head)->hh.tbl->hho)) : NULL); \
_hs_qsize--; \
} \
if ( _hs_tail ) { \
_hs_tail->next = ((_hs_e) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
} else { \
_hs_list = _hs_e; \
} \
_hs_e->prev = ((_hs_tail) ? \
ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
_hs_tail = _hs_e; \
} \
_hs_p = _hs_q; \
} \
_hs_tail->next = NULL; \
if ( _hs_nmerges <= 1 ) { \
_hs_looping=0; \
(head)->hh.tbl->tail = _hs_tail; \
DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
} \
_hs_insize *= 2; \
} \
HASH_FSCK(hh,head); \
} \
} while (0)
/* This function selects items from one hash into another hash.
* The end result is that the selected items have dual presence
* in both hashes. There is no copy of the items made; rather
* they are added into the new hash through a secondary hash
* hash handle that must be present in the structure. */
#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
do { \
unsigned _src_bkt, _dst_bkt; \
void *_last_elt=NULL, *_elt; \
UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
if (src) { \
for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
_src_hh; \
_src_hh = _src_hh->hh_next) { \
_elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
if (cond(_elt)) { \
_dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
_dst_hh->key = _src_hh->key; \
_dst_hh->keylen = _src_hh->keylen; \
_dst_hh->hashv = _src_hh->hashv; \
_dst_hh->prev = _last_elt; \
_dst_hh->next = NULL; \
if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
if (!dst) { \
DECLTYPE_ASSIGN(dst,_elt); \
HASH_MAKE_TABLE(hh_dst,dst); \
} else { \
_dst_hh->tbl = (dst)->hh_dst.tbl; \
} \
HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
(dst)->hh_dst.tbl->num_items++; \
_last_elt = _elt; \
_last_elt_hh = _dst_hh; \
} \
} \
} \
} \
HASH_FSCK(hh_dst,dst); \
} while (0)
#define HASH_CLEAR(hh,head) \
do { \
if (head) { \
uthash_free((head)->hh.tbl->buckets, \
(head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
(head)=NULL; \
} \
} while(0)
#ifdef NO_DECLTYPE
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
#else
#define HASH_ITER(hh,head,el,tmp) \
for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
#endif
/* obtain a count of items in the hash */
#define HASH_COUNT(head) HASH_CNT(hh,head)
#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
typedef struct UT_hash_bucket {
struct UT_hash_handle *hh_head;
unsigned count;
/* expand_mult is normally set to 0. In this situation, the max chain length
* threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
* the bucket's chain exceeds this length, bucket expansion is triggered).
* However, setting expand_mult to a non-zero value delays bucket expansion
* (that would be triggered by additions to this particular bucket)
* until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
* (The multiplier is simply expand_mult+1). The whole idea of this
* multiplier is to reduce bucket expansions, since they are expensive, in
* situations where we know that a particular bucket tends to be overused.
* It is better to let its chain length grow to a longer yet-still-bounded
* value, than to do an O(n) bucket expansion too often.
*/
unsigned expand_mult;
} UT_hash_bucket;
/* random signature used only to find hash tables in external analysis */
#define HASH_SIGNATURE 0xa0111fe1
#define HASH_BLOOM_SIGNATURE 0xb12220f2
typedef struct UT_hash_table {
UT_hash_bucket *buckets;
unsigned num_buckets, log2_num_buckets;
unsigned num_items;
struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
/* in an ideal situation (all buckets used equally), no bucket would have
* more than ceil(#items/#buckets) items. that's the ideal chain length. */
unsigned ideal_chain_maxlen;
/* nonideal_items is the number of items in the hash whose chain position
* exceeds the ideal chain maxlen. these items pay the penalty for an uneven
* hash distribution; reaching them in a chain traversal takes >ideal steps */
unsigned nonideal_items;
/* ineffective expands occur when a bucket doubling was performed, but
* afterward, more than half the items in the hash had nonideal chain
* positions. If this happens on two consecutive expansions we inhibit any
* further expansion, as it's not helping; this happens when the hash
* function isn't a good fit for the key domain. When expansion is inhibited
* the hash will still work, albeit no longer in constant time. */
unsigned ineff_expands, noexpand;
uint32_t signature; /* used only to find hash tables in external analysis */
#ifdef HASH_BLOOM
uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
uint8_t *bloom_bv;
char bloom_nbits;
#endif
} UT_hash_table;
typedef struct UT_hash_handle {
struct UT_hash_table *tbl;
void *prev; /* prev element in app order */
void *next; /* next element in app order */
struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
struct UT_hash_handle *hh_next; /* next hh in bucket order */
void *key; /* ptr to enclosing struct's key */
unsigned keylen; /* enclosing struct's key len */
unsigned hashv; /* result of hash-fcn(key) */
} UT_hash_handle;
#endif /* UTHASH_H */
@@ -0,0 +1,24 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifndef _AR_H_
#define _AR_H_ 1
#define ARMAG "!<arch>\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6], ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
};
#endif
@@ -0,0 +1,57 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifndef _COMPAT_H_
#define _COMPAT_H_ 1
#pragma warning(disable:4244 4267)
#include <sys/cdefs.h>
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include "sys/mman.h"
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef uint8_t u_int8_t;
typedef uint16_t u_int16_t;
typedef uint32_t u_int32_t;
typedef uint64_t u_int64_t;
#ifndef _WIN64
typedef __int32 ssize_t;
#else // _WIN64
typedef __int64 ssize_t;
#endif // _WIN64
typedef long uid_t;
typedef long gid_t;
typedef long mode_t;
typedef long off_t;
#if _MSC_VER < 1900
#ifndef snprintf
# define snprintf sprintf_s
#endif
#ifndef fstat
# define fstat(A, B) _fstat((A), (struct _stat*)(B))
#endif
#endif
#ifndef S_ISCHR
#define S_ISCHR(A) (((A) & S_IFMT) == S_IFCHR)
#endif
#ifndef S_ISREG
#define S_ISREG(A) (((A) & S_IFMT) == S_IFREG)
#endif
#endif
@@ -0,0 +1,19 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifndef _SYS_CDEFS_H_
#define _SYS_CDEFS_H_ 1
#ifdef __cplusplus
# define __BEGIN_DECLS extern "C" {
# define __END_DECLS }
#else
# define __BEGIN_DECLS
# define __END_DECLS
#endif
#endif
@@ -0,0 +1,163 @@
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* 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.
*
* $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $
*/
#ifndef _SYS_ELF32_H_
#define _SYS_ELF32_H_ 1
#include "elf_common.h"
/*
* ELF definitions common to all 32-bit architectures.
*/
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef Elf32_Word Elf32_Hashelt;
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf32_Word Elf32_Size;
typedef Elf32_Sword Elf32_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
Elf32_Half e_machine; /* Machine architecture. */
Elf32_Word e_version; /* ELF format version. */
Elf32_Addr e_entry; /* Entry point. */
Elf32_Off e_phoff; /* Program header file offset. */
Elf32_Off e_shoff; /* Section header file offset. */
Elf32_Word e_flags; /* Architecture-specific flags. */
Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
Elf32_Half e_phentsize; /* Size of program header entry. */
Elf32_Half e_phnum; /* Number of program header entries. */
Elf32_Half e_shentsize; /* Size of section header entry. */
Elf32_Half e_shnum; /* Number of section header entries. */
Elf32_Half e_shstrndx; /* Section name strings section. */
} Elf32_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf32_Word sh_name; /* Section name (index into the
section header string table). */
Elf32_Word sh_type; /* Section type. */
Elf32_Word sh_flags; /* Section flags. */
Elf32_Addr sh_addr; /* Address in memory image. */
Elf32_Off sh_offset; /* Offset in file. */
Elf32_Word sh_size; /* Size in bytes. */
Elf32_Word sh_link; /* Index of a related section. */
Elf32_Word sh_info; /* Depends on section type. */
Elf32_Word sh_addralign; /* Alignment in bytes. */
Elf32_Word sh_entsize; /* Size of each entry in section. */
} Elf32_Shdr;
/*
* Program header.
*/
typedef struct {
Elf32_Word p_type; /* Entry type. */
Elf32_Off p_offset; /* File offset of contents. */
Elf32_Addr p_vaddr; /* Virtual address in memory image. */
Elf32_Addr p_paddr; /* Physical address (not used). */
Elf32_Word p_filesz; /* Size of contents in file. */
Elf32_Word p_memsz; /* Size of contents in memory. */
Elf32_Word p_flags; /* Access permission flags. */
Elf32_Word p_align; /* Alignment in memory and file. */
} Elf32_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf32_Sword d_tag; /* Entry type. */
union {
Elf32_Word d_val; /* Integer value. */
Elf32_Addr d_ptr; /* Address value. */
} d_un;
} Elf32_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
} Elf32_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
Elf32_Sword r_addend; /* Addend. */
} Elf32_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF32_R_SYM(info) ((info) >> 8)
#define ELF32_R_TYPE(info) ((unsigned char)(info))
/* Macro for constructing r_info from field values. */
#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type))
/*
* Symbol table entries.
*/
typedef struct {
Elf32_Word st_name; /* String table index of name. */
Elf32_Addr st_value; /* Symbol value. */
Elf32_Word st_size; /* Size of associated object. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf32_Half st_shndx; /* Section index of symbol. */
} Elf32_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF32_ST_BIND(info) ((info) >> 4)
#define ELF32_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3)
#endif /* !_SYS_ELF32_H_ */
@@ -0,0 +1,176 @@
/*-
* Copyright (c) 1996-1998 John D. Polstra.
* 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.
*
* $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $
*/
#ifndef _SYS_ELF64_H_
#define _SYS_ELF64_H_ 1
#include "elf_common.h"
/*
* ELF definitions common to all 64-bit architectures.
*/
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Xword;
/*
* Types of dynamic symbol hash table bucket and chain elements.
*
* This is inconsistent among 64 bit architectures, so a machine dependent
* typedef is required.
*/
#ifdef __alpha__
typedef Elf64_Off Elf64_Hashelt;
#else
typedef Elf64_Word Elf64_Hashelt;
#endif
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf64_Xword Elf64_Size;
typedef Elf64_Sxword Elf64_Ssize;
/*
* ELF header.
*/
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf64_Half e_type; /* File type. */
Elf64_Half e_machine; /* Machine architecture. */
Elf64_Word e_version; /* ELF format version. */
Elf64_Addr e_entry; /* Entry point. */
Elf64_Off e_phoff; /* Program header file offset. */
Elf64_Off e_shoff; /* Section header file offset. */
Elf64_Word e_flags; /* Architecture-specific flags. */
Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
Elf64_Half e_phentsize; /* Size of program header entry. */
Elf64_Half e_phnum; /* Number of program header entries. */
Elf64_Half e_shentsize; /* Size of section header entry. */
Elf64_Half e_shnum; /* Number of section header entries. */
Elf64_Half e_shstrndx; /* Section name strings section. */
} Elf64_Ehdr;
/*
* Section header.
*/
typedef struct {
Elf64_Word sh_name; /* Section name (index into the
section header string table). */
Elf64_Word sh_type; /* Section type. */
Elf64_Xword sh_flags; /* Section flags. */
Elf64_Addr sh_addr; /* Address in memory image. */
Elf64_Off sh_offset; /* Offset in file. */
Elf64_Xword sh_size; /* Size in bytes. */
Elf64_Word sh_link; /* Index of a related section. */
Elf64_Word sh_info; /* Depends on section type. */
Elf64_Xword sh_addralign; /* Alignment in bytes. */
Elf64_Xword sh_entsize; /* Size of each entry in section. */
} Elf64_Shdr;
/*
* Program header.
*/
typedef struct {
Elf64_Word p_type; /* Entry type. */
Elf64_Word p_flags; /* Access permission flags. */
Elf64_Off p_offset; /* File offset of contents. */
Elf64_Addr p_vaddr; /* Virtual address in memory image. */
Elf64_Addr p_paddr; /* Physical address (not used). */
Elf64_Xword p_filesz; /* Size of contents in file. */
Elf64_Xword p_memsz; /* Size of contents in memory. */
Elf64_Xword p_align; /* Alignment in memory and file. */
} Elf64_Phdr;
/*
* Dynamic structure. The ".dynamic" section contains an array of them.
*/
typedef struct {
Elf64_Sxword d_tag; /* Entry type. */
union {
Elf64_Xword d_val; /* Integer value. */
Elf64_Addr d_ptr; /* Address value. */
} d_un;
} Elf64_Dyn;
/*
* Relocation entries.
*/
/* Relocations that don't need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
} Elf64_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
Elf64_Sxword r_addend; /* Addend. */
} Elf64_Rela;
/* Macros for accessing the fields of r_info. */
#define ELF64_R_SYM(info) ((info) >> 32)
#define ELF64_R_TYPE(info) ((info) & 0xffffffffL)
/* Macro for constructing r_info from field values. */
#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL))
/*
* Symbol table entries.
*/
typedef struct {
Elf64_Word st_name; /* String table index of name. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf64_Half st_shndx; /* Section index of symbol. */
Elf64_Addr st_value; /* Symbol value. */
Elf64_Xword st_size; /* Size of associated object. */
} Elf64_Sym;
/* Macros for accessing the fields of st_info. */
#define ELF64_ST_BIND(info) ((info) >> 4)
#define ELF64_ST_TYPE(info) ((info) & 0xf)
/* Macro for constructing st_info from field values. */
#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
/* Macro for accessing the fields of st_other. */
#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3)
#endif /* !_SYS_ELF64_H_ */
@@ -0,0 +1,355 @@
/*-
* Copyright (c) 1998 John D. Polstra.
* 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.
*
* $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $
*/
#ifndef _SYS_ELF_COMMON_H_
#define _SYS_ELF_COMMON_H_ 1
/*
* ELF definitions that are independent of architecture or word size.
*/
/*
* Note header. The ".note" section contains an array of notes. Each
* begins with this header, aligned to a word boundary. Immediately
* following the note header is n_namesz bytes of name, padded to the
* next word boundary. Then comes n_descsz bytes of descriptor, again
* padded to a word boundary. The values of n_namesz and n_descsz do
* not include the padding.
*/
typedef struct {
u_int32_t n_namesz; /* Length of name. */
u_int32_t n_descsz; /* Length of descriptor. */
u_int32_t n_type; /* Type of this note. */
} Elf_Note;
/* Indexes into the e_ident array. Keep synced with
http://www.sco.com/developer/gabi/ch4.eheader.html */
#define EI_MAG0 0 /* Magic number, byte 0. */
#define EI_MAG1 1 /* Magic number, byte 1. */
#define EI_MAG2 2 /* Magic number, byte 2. */
#define EI_MAG3 3 /* Magic number, byte 3. */
#define EI_CLASS 4 /* Class of machine. */
#define EI_DATA 5 /* Data format. */
#define EI_VERSION 6 /* ELF format version. */
#define EI_OSABI 7 /* Operating system / ABI identification */
#define EI_ABIVERSION 8 /* ABI version */
#define OLD_EI_BRAND 8 /* Start of architecture identification. */
#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */
#define EI_NIDENT 16 /* Size of e_ident array. */
/* Values for the magic number bytes. */
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFMAG "\177ELF" /* magic string */
#define SELFMAG 4 /* magic string size */
/* Values for e_ident[EI_VERSION] and e_version. */
#define EV_NONE 0
#define EV_CURRENT 1
/* Values for e_ident[EI_CLASS]. */
#define ELFCLASSNONE 0 /* Unknown class. */
#define ELFCLASS32 1 /* 32-bit architecture. */
#define ELFCLASS64 2 /* 64-bit architecture. */
/* Values for e_ident[EI_DATA]. */
#define ELFDATANONE 0 /* Unknown data format. */
#define ELFDATA2LSB 1 /* 2's complement little-endian. */
#define ELFDATA2MSB 2 /* 2's complement big-endian. */
/* Values for e_ident[EI_OSABI]. */
#define ELFOSABI_NONE 0 /* UNIX System V ABI */
#define ELFOSABI_HPUX 1 /* HP-UX operating system */
#define ELFOSABI_NETBSD 2 /* NetBSD */
#define ELFOSABI_LINUX 3 /* GNU/Linux */
#define ELFOSABI_HURD 4 /* GNU/Hurd */
#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */
#define ELFOSABI_SOLARIS 6 /* Solaris */
#define ELFOSABI_AIX 7 /* AIX */
#define ELFOSABI_IRIX 8 /* IRIX */
#define ELFOSABI_FREEBSD 9 /* FreeBSD */
#define ELFOSABI_TRU64 10 /* TRU64 UNIX */
#define ELFOSABI_MODESTO 11 /* Novell Modesto */
#define ELFOSABI_OPENBSD 12 /* OpenBSD */
#define ELFOSABI_OPENVMS 13 /* Open VMS */
#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */
#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */
#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */
/* e_ident */
#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
(ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
(ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
(ehdr).e_ident[EI_MAG3] == ELFMAG3)
/* Values for e_type. */
#define ET_NONE 0 /* Unknown type. */
#define ET_REL 1 /* Relocatable. */
#define ET_EXEC 2 /* Executable. */
#define ET_DYN 3 /* Shared object. */
#define ET_CORE 4 /* Core file. */
#define ET_LOOS 0xfe00 /* First operating system specific. */
#define ET_HIOS 0xfeff /* Last operating system-specific. */
#define ET_LOPROC 0xff00 /* First processor-specific. */
#define ET_HIPROC 0xffff /* Last processor-specific. */
/* Values for e_machine. */
#define EM_NONE 0 /* Unknown machine. */
#define EM_M32 1 /* AT&T WE32100. */
#define EM_SPARC 2 /* Sun SPARC. */
#define EM_386 3 /* Intel i386. */
#define EM_68K 4 /* Motorola 68000. */
#define EM_88K 5 /* Motorola 88000. */
#define EM_860 7 /* Intel i860. */
#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */
#define EM_S370 9 /* IBM System/370. */
#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */
#define EM_PARISC 15 /* HP PA-RISC. */
#define EM_VPP500 17 /* Fujitsu VPP500. */
#define EM_SPARC32PLUS 18 /* SPARC v8plus. */
#define EM_960 19 /* Intel 80960. */
#define EM_PPC 20 /* PowerPC 32-bit. */
#define EM_PPC64 21 /* PowerPC 64-bit. */
#define EM_S390 22 /* IBM System/390. */
#define EM_V800 36 /* NEC V800. */
#define EM_FR20 37 /* Fujitsu FR20. */
#define EM_RH32 38 /* TRW RH-32. */
#define EM_RCE 39 /* Motorola RCE. */
#define EM_ARM 40 /* ARM. */
#define EM_SH 42 /* Hitachi SH. */
#define EM_SPARCV9 43 /* SPARC v9 64-bit. */
#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */
#define EM_ARC 45 /* Argonaut RISC Core. */
#define EM_H8_300 46 /* Hitachi H8/300. */
#define EM_H8_300H 47 /* Hitachi H8/300H. */
#define EM_H8S 48 /* Hitachi H8S. */
#define EM_H8_500 49 /* Hitachi H8/500. */
#define EM_IA_64 50 /* Intel IA-64 Processor. */
#define EM_MIPS_X 51 /* Stanford MIPS-X. */
#define EM_COLDFIRE 52 /* Motorola ColdFire. */
#define EM_68HC12 53 /* Motorola M68HC12. */
#define EM_MMA 54 /* Fujitsu MMA. */
#define EM_PCP 55 /* Siemens PCP. */
#define EM_NCPU 56 /* Sony nCPU. */
#define EM_NDR1 57 /* Denso NDR1 microprocessor. */
#define EM_STARCORE 58 /* Motorola Star*Core processor. */
#define EM_ME16 59 /* Toyota ME16 processor. */
#define EM_ST100 60 /* STMicroelectronics ST100 processor. */
#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */
#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */
/* Non-standard or deprecated. */
#define EM_486 6 /* Intel i486. */
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */
#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */
/* Special section indexes. */
#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */
#define SHN_LORESERVE 0xff00 /* First of reserved range. */
#define SHN_LOPROC 0xff00 /* First processor-specific. */
#define SHN_HIPROC 0xff1f /* Last processor-specific. */
#define SHN_LOOS 0xff20 /* First operating system-specific. */
#define SHN_HIOS 0xff3f /* Last operating system-specific. */
#define SHN_ABS 0xfff1 /* Absolute values. */
#define SHN_COMMON 0xfff2 /* Common data. */
#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */
#define SHN_HIRESERVE 0xffff /* Last of reserved range. */
/* sh_type */
#define SHT_NULL 0 /* inactive */
#define SHT_PROGBITS 1 /* program defined information */
#define SHT_SYMTAB 2 /* symbol table section */
#define SHT_STRTAB 3 /* string table section */
#define SHT_RELA 4 /* relocation section with addends */
#define SHT_HASH 5 /* symbol hash table section */
#define SHT_DYNAMIC 6 /* dynamic section */
#define SHT_NOTE 7 /* note section */
#define SHT_NOBITS 8 /* no space section */
#define SHT_REL 9 /* relocation section - no addends */
#define SHT_SHLIB 10 /* reserved - purpose unknown */
#define SHT_DYNSYM 11 /* dynamic symbol table section */
#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */
#define SHT_FINI_ARRAY 15 /* Termination function pointers. */
#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */
#define SHT_GROUP 17 /* Section group. */
#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */
#define SHT_LOOS 0x60000000 /* First of OS specific semantics */
#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */
#define SHT_LOPROC 0x70000000 /* reserved range for processor */
#define SHT_HIPROC 0x7fffffff /* specific section header types */
#define SHT_LOUSER 0x80000000 /* reserved range for application */
#define SHT_HIUSER 0xffffffff /* specific indexes */
/* Flags for sh_flags. */
#define SHF_WRITE 0x1 /* Section contains writable data. */
#define SHF_ALLOC 0x2 /* Section occupies memory. */
#define SHF_EXECINSTR 0x4 /* Section contains instructions. */
#define SHF_MERGE 0x10 /* Section may be merged. */
#define SHF_STRINGS 0x20 /* Section contains strings. */
#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */
#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */
#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */
#define SHF_GROUP 0x200 /* Member of section group. */
#define SHF_TLS 0x400 /* Section contains TLS data. */
#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */
#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */
/* Values for p_type. */
#define PT_NULL 0 /* Unused entry. */
#define PT_LOAD 1 /* Loadable segment. */
#define PT_DYNAMIC 2 /* Dynamic linking information segment. */
#define PT_INTERP 3 /* Pathname of interpreter. */
#define PT_NOTE 4 /* Auxiliary information. */
#define PT_SHLIB 5 /* Reserved (not used). */
#define PT_PHDR 6 /* Location of program header itself. */
#define PT_TLS 7 /* Thread local storage segment */
#define PT_LOOS 0x60000000 /* First OS-specific. */
#define PT_HIOS 0x6fffffff /* Last OS-specific. */
#define PT_LOPROC 0x70000000 /* First processor-specific type. */
#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */
/* Values for p_flags. */
#define PF_X 0x1 /* Executable. */
#define PF_W 0x2 /* Writable. */
#define PF_R 0x4 /* Readable. */
#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */
#define PF_MASKPROC 0xf0000000 /* Processor-specific. */
/* Values for d_tag. */
#define DT_NULL 0 /* Terminating entry. */
#define DT_NEEDED 1 /* String table offset of a needed shared
library. */
#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */
#define DT_PLTGOT 3 /* Processor-dependent address. */
#define DT_HASH 4 /* Address of symbol hash table. */
#define DT_STRTAB 5 /* Address of string table. */
#define DT_SYMTAB 6 /* Address of symbol table. */
#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */
#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */
#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */
#define DT_STRSZ 10 /* Size of string table. */
#define DT_SYMENT 11 /* Size of each symbol table entry. */
#define DT_INIT 12 /* Address of initialization function. */
#define DT_FINI 13 /* Address of finalization function. */
#define DT_SONAME 14 /* String table offset of shared object
name. */
#define DT_RPATH 15 /* String table offset of library path. [sup] */
#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */
#define DT_REL 17 /* Address of ElfNN_Rel relocations. */
#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */
#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */
#define DT_PLTREL 20 /* Type of relocation used for PLT. */
#define DT_DEBUG 21 /* Reserved (not used). */
#define DT_TEXTREL 22 /* Indicates there may be relocations in
non-writable segments. [sup] */
#define DT_JMPREL 23 /* Address of PLT relocations. */
#define DT_BIND_NOW 24 /* [sup] */
#define DT_INIT_ARRAY 25 /* Address of the array of pointers to
initialization functions */
#define DT_FINI_ARRAY 26 /* Address of the array of pointers to
termination functions */
#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of
initialization functions. */
#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of
terminationfunctions. */
#define DT_RUNPATH 29 /* String table offset of a null-terminated
library search path string. */
#define DT_FLAGS 30 /* Object specific flag values. */
#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING
and less than DT_LOOS follow the rules for
the interpretation of the d_un union
as follows: even == 'd_ptr', even == 'd_val'
or none */
#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to
pre-initialization functions. */
#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of
pre-initialization functions. */
#define DT_LOOS 0x6000000d /* First OS-specific */
#define DT_HIOS 0x6ffff000 /* Last OS-specific */
#define DT_LOPROC 0x70000000 /* First processor-specific type. */
#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */
/* Values for DT_FLAGS */
#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may
make reference to the $ORIGIN substitution
string */
#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */
#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in
non-writable segments. */
#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should
process all relocations for the object
containing this entry before transferring
control to the program. */
#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or
executable contains code using a static
thread-local storage scheme. */
/* Values for n_type. Used in core files. */
#define NT_PRSTATUS 1 /* Process status. */
#define NT_FPREGSET 2 /* Floating point registers. */
#define NT_PRPSINFO 3 /* Process state info. */
/* Symbol Binding - ELFNN_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */
#define STB_GLOBAL 1 /* Global symbol */
#define STB_WEAK 2 /* like global - lower precedence */
#define STB_LOOS 10 /* Reserved range for operating system */
#define STB_HIOS 12 /* specific semantics. */
#define STB_LOPROC 13 /* reserved range for processor */
#define STB_HIPROC 15 /* specific semantics. */
/* Symbol type - ELFNN_ST_TYPE - st_info */
#define STT_NOTYPE 0 /* Unspecified type. */
#define STT_OBJECT 1 /* Data object. */
#define STT_FUNC 2 /* Function. */
#define STT_SECTION 3 /* Section. */
#define STT_FILE 4 /* Source file. */
#define STT_COMMON 5 /* Uninitialized common block. */
#define STT_TLS 6 /* TLS object. */
#define STT_LOOS 10 /* Reserved range for operating system */
#define STT_HIOS 12 /* specific semantics. */
#define STT_LOPROC 13 /* reserved range for processor */
#define STT_HIPROC 15 /* specific semantics. */
/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */
#define STV_DEFAULT 0x0 /* Default visibility (see binding). */
#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */
#define STV_HIDDEN 0x2 /* Not visible. */
#define STV_PROTECTED 0x3 /* Visible but not preemptible. */
/* Special symbol table indexes. */
#define STN_UNDEF 0 /* Undefined symbol index. */
#endif /* !_SYS_ELF_COMMON_H_ */
@@ -0,0 +1,15 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifndef _MMAN_H_
#define _MMAN_H_
#if defined(WIN32)
void *mmap(void*, size_t, int, int, int, unsigned);
int munmap(void*, size_t);
#endif
#endif // _MMAN_H_
@@ -0,0 +1,13 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifndef _SYS_PARAM_H_
#define _SYS_PARAM_H_ 1
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#endif
@@ -0,0 +1,671 @@
/* $NetBSD: queue.h,v 1.45.14.2 2009/06/05 16:23:34 snj Exp $ */
/*
* 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.
*
* @(#)queue.h 8.5 (Berkeley) 8/20/94
*/
#ifndef _ELF_SYS_QUEUE_H_
#define _ELF_SYS_QUEUE_H_
/*
* This file defines five types of data structures: singly-linked lists,
* lists, simple queues, tail queues, and circular queues.
*
* A singly-linked list is headed by a single forward pointer. The
* elements are singly linked for minimum space and pointer manipulation
* overhead at the expense of O(n) removal for arbitrary elements. New
* elements can be added to the list after an existing element or at the
* head of the list. Elements being removed from the head of the list
* should use the explicit macro for this purpose for optimum
* efficiency. A singly-linked list may only be traversed in the forward
* direction. Singly-linked lists are ideal for applications with large
* datasets and few or no removals or for implementing a LIFO queue.
*
* A list is headed by a single forward pointer (or an array of forward
* pointers for a hash table header). The elements are doubly linked
* so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before
* or after an existing element or at the head of the list. A list
* may only be traversed in the forward direction.
*
* A simple queue is headed by a pair of pointers, one the head of the
* list and the other to the tail of the list. The elements are singly
* linked to save space, so elements can only be removed from the
* head of the list. New elements can be added to the list after
* an existing element, at the head of the list, or at the end of the
* list. A simple queue may only be traversed in the forward direction.
*
* A tail queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or
* after an existing element, at the head of the list, or at the end of
* the list. A tail queue may be traversed in either direction.
*
* A circle queue is headed by a pair of pointers, one to the head of the
* list and the other to the tail of the list. The elements are doubly
* linked so that an arbitrary element can be removed without a need to
* traverse the list. New elements can be added to the list before or after
* an existing element, at the head of the list, or at the end of the list.
* A circle queue may be traversed in either direction, but has a more
* complex end of list detection.
*
* For details on the use of these macros, see the queue(3) manual page.
*/
/*
* List definitions.
*/
#define LIST_HEAD(name, type) \
struct name { \
struct type *lh_first; /* first element */ \
}
#define LIST_HEAD_INITIALIZER(head) \
{ NULL }
#define LIST_ENTRY(type) \
struct { \
struct type *le_next; /* next element */ \
struct type **le_prev; /* address of previous next element */ \
}
/*
* List functions.
*/
#if defined(_KERNEL) && defined(QUEUEDEBUG)
#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
if ((head)->lh_first && \
(head)->lh_first->field.le_prev != &(head)->lh_first) \
panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
#define QUEUEDEBUG_LIST_OP(elm, field) \
if ((elm)->field.le_next && \
(elm)->field.le_next->field.le_prev != \
&(elm)->field.le_next) \
panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
if (*(elm)->field.le_prev != (elm)) \
panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
(elm)->field.le_next = (void *)1L; \
(elm)->field.le_prev = (void *)1L;
#else
#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
#define QUEUEDEBUG_LIST_OP(elm, field)
#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
#endif
#define LIST_INIT(head) do { \
(head)->lh_first = NULL; \
} while (/*CONSTCOND*/0)
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
QUEUEDEBUG_LIST_OP((listelm), field) \
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
(listelm)->field.le_next->field.le_prev = \
&(elm)->field.le_next; \
(listelm)->field.le_next = (elm); \
(elm)->field.le_prev = &(listelm)->field.le_next; \
} while (/*CONSTCOND*/0)
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
QUEUEDEBUG_LIST_OP((listelm), field) \
(elm)->field.le_prev = (listelm)->field.le_prev; \
(elm)->field.le_next = (listelm); \
*(listelm)->field.le_prev = (elm); \
(listelm)->field.le_prev = &(elm)->field.le_next; \
} while (/*CONSTCOND*/0)
#define LIST_INSERT_HEAD(head, elm, field) do { \
QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
(head)->lh_first = (elm); \
(elm)->field.le_prev = &(head)->lh_first; \
} while (/*CONSTCOND*/0)
#define LIST_REMOVE(elm, field) do { \
QUEUEDEBUG_LIST_OP((elm), field) \
if ((elm)->field.le_next != NULL) \
(elm)->field.le_next->field.le_prev = \
(elm)->field.le_prev; \
*(elm)->field.le_prev = (elm)->field.le_next; \
QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
} while (/*CONSTCOND*/0)
#define LIST_FOREACH(var, head, field) \
for ((var) = ((head)->lh_first); \
(var); \
(var) = ((var)->field.le_next))
/*
* List access methods.
*/
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
#define LIST_FIRST(head) ((head)->lh_first)
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
/*
* Singly-linked List definitions.
*/
#define ELF_SLIST_HEAD(name, type) \
struct name { \
struct type *slh_first; /* first element */ \
}
#define ELF_SLIST_HEAD_INITIALIZER(head) \
{ NULL }
#define ELF_SLIST_ENTRY(type) \
struct { \
struct type *sle_next; /* next element */ \
}
/*
* Singly-linked List functions.
*/
#define ELF_SLIST_INIT(head) do { \
(head)->slh_first = NULL; \
} while (/*CONSTCOND*/0)
#define ELF_SLIST_INSERT_AFTER(slistelm, elm, field) do { \
(elm)->field.sle_next = (slistelm)->field.sle_next; \
(slistelm)->field.sle_next = (elm); \
} while (/*CONSTCOND*/0)
#define ELF_SLIST_INSERT_HEAD(head, elm, field) do { \
(elm)->field.sle_next = (head)->slh_first; \
(head)->slh_first = (elm); \
} while (/*CONSTCOND*/0)
#define ELF_SLIST_REMOVE_HEAD(head, field) do { \
(head)->slh_first = (head)->slh_first->field.sle_next; \
} while (/*CONSTCOND*/0)
#define ELF_SLIST_REMOVE(head, elm, type, field) do { \
if ((head)->slh_first == (elm)) { \
ELF_SLIST_REMOVE_HEAD((head), field); \
} \
else { \
struct type *curelm = (head)->slh_first; \
while(curelm->field.sle_next != (elm)) \
curelm = curelm->field.sle_next; \
curelm->field.sle_next = \
curelm->field.sle_next->field.sle_next; \
} \
} while (/*CONSTCOND*/0)
#define ELF_SLIST_FOREACH(var, head, field) \
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
/*
* Singly-linked List access methods.
*/
#define ELF_SLIST_EMPTY(head) ((head)->slh_first == NULL)
#define ELF_SLIST_FIRST(head) ((head)->slh_first)
#define ELF_SLIST_NEXT(elm, field) ((elm)->field.sle_next)
/*
* Singly-linked Tail queue declarations.
*/
#define STAILQ_HEAD(name, type) \
struct name { \
struct type *stqh_first; /* first element */ \
struct type **stqh_last; /* addr of last next element */ \
}
#define STAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).stqh_first }
#define STAILQ_ENTRY(type) \
struct { \
struct type *stqe_next; /* next element */ \
}
/*
* Singly-linked Tail queue functions.
*/
#define STAILQ_INIT(head) do { \
(head)->stqh_first = NULL; \
(head)->stqh_last = &(head)->stqh_first; \
} while (/*CONSTCOND*/0)
#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)
#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)
#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)
#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)
#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)
#define STAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->stqh_first); \
(var); \
(var) = ((var)->field.stqe_next))
/*
* Singly-linked Tail queue access methods.
*/
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
#define STAILQ_FIRST(head) ((head)->stqh_first)
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
/*
* Simple queue definitions.
*/
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
#define SIMPLEQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).sqh_first }
#define SIMPLEQ_ENTRY(type) \
struct { \
struct type *sqe_next; /* next element */ \
}
/*
* Simple queue functions.
*/
#define SIMPLEQ_INIT(head) do { \
(head)->sqh_first = NULL; \
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
(head)->sqh_last = &(elm)->field.sqe_next; \
(head)->sqh_first = (elm); \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
(elm)->field.sqe_next = NULL; \
*(head)->sqh_last = (elm); \
(head)->sqh_last = &(elm)->field.sqe_next; \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
(head)->sqh_last = &(elm)->field.sqe_next; \
(listelm)->field.sqe_next = (elm); \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
(head)->sqh_last = &(head)->sqh_first; \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
if ((head)->sqh_first == (elm)) { \
SIMPLEQ_REMOVE_HEAD((head), field); \
} else { \
struct type *curelm = (head)->sqh_first; \
while (curelm->field.sqe_next != (elm)) \
curelm = curelm->field.sqe_next; \
if ((curelm->field.sqe_next = \
curelm->field.sqe_next->field.sqe_next) == NULL) \
(head)->sqh_last = &(curelm)->field.sqe_next; \
} \
} while (/*CONSTCOND*/0)
#define SIMPLEQ_FOREACH(var, head, field) \
for ((var) = ((head)->sqh_first); \
(var); \
(var) = ((var)->field.sqe_next))
/*
* Simple queue access methods.
*/
#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
/*
* Tail queue definitions.
*/
#define _TAILQ_HEAD(name, type, qual) \
struct name { \
qual type *tqh_first; /* first element */ \
qual type *qual *tqh_last; /* addr of last next element */ \
}
#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
#define TAILQ_HEAD_INITIALIZER(head) \
{ NULL, &(head).tqh_first }
#define _TAILQ_ENTRY(type, qual) \
struct { \
qual type *tqe_next; /* next element */ \
qual type *qual *tqe_prev; /* address of previous next element */\
}
#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
/*
* Tail queue functions.
*/
#if defined(_KERNEL) && defined(QUEUEDEBUG)
#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
if ((head)->tqh_first && \
(head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
if (*(head)->tqh_last != NULL) \
panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__);
#define QUEUEDEBUG_TAILQ_OP(elm, field) \
if ((elm)->field.tqe_next && \
(elm)->field.tqe_next->field.tqe_prev != \
&(elm)->field.tqe_next) \
panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
if (*(elm)->field.tqe_prev != (elm)) \
panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__);
#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
if ((elm)->field.tqe_next == NULL && \
(head)->tqh_last != &(elm)->field.tqe_next) \
panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \
(head), (elm), __FILE__, __LINE__);
#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
(elm)->field.tqe_next = (void *)1L; \
(elm)->field.tqe_prev = (void *)1L;
#else
#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
#define QUEUEDEBUG_TAILQ_OP(elm, field)
#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
#endif
#define TAILQ_INIT(head) do { \
(head)->tqh_first = NULL; \
(head)->tqh_last = &(head)->tqh_first; \
} while (/*CONSTCOND*/0)
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
(head)->tqh_first->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(head)->tqh_first = (elm); \
(elm)->field.tqe_prev = &(head)->tqh_first; \
} while (/*CONSTCOND*/0)
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
(elm)->field.tqe_next = NULL; \
(elm)->field.tqe_prev = (head)->tqh_last; \
*(head)->tqh_last = (elm); \
(head)->tqh_last = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
QUEUEDEBUG_TAILQ_OP((listelm), field) \
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
(elm)->field.tqe_next->field.tqe_prev = \
&(elm)->field.tqe_next; \
else \
(head)->tqh_last = &(elm)->field.tqe_next; \
(listelm)->field.tqe_next = (elm); \
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
QUEUEDEBUG_TAILQ_OP((listelm), field) \
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
(elm)->field.tqe_next = (listelm); \
*(listelm)->field.tqe_prev = (elm); \
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
} while (/*CONSTCOND*/0)
#define TAILQ_REMOVE(head, elm, field) do { \
QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
QUEUEDEBUG_TAILQ_OP((elm), field) \
if (((elm)->field.tqe_next) != NULL) \
(elm)->field.tqe_next->field.tqe_prev = \
(elm)->field.tqe_prev; \
else \
(head)->tqh_last = (elm)->field.tqe_prev; \
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
} while (/*CONSTCOND*/0)
#define TAILQ_FOREACH(var, head, field) \
for ((var) = ((head)->tqh_first); \
(var); \
(var) = ((var)->field.tqe_next))
#define TAILQ_FOREACH_SAFE(var, head, field, next) \
for ((var) = ((head)->tqh_first); \
(var) != NULL && ((next) = TAILQ_NEXT(var, field), 1); \
(var) = (next))
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
(var); \
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
/*
* Tail queue access methods.
*/
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
#define TAILQ_FIRST(head) ((head)->tqh_first)
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
#define TAILQ_LAST(head, headname) \
(*(((struct headname *)((head)->tqh_last))->tqh_last))
#define TAILQ_PREV(elm, headname, field) \
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
/*
* Circular queue definitions.
*/
#if defined(_KERNEL) && defined(QUEUEDEBUG)
#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
if ((head)->cqh_first != (void *)(head) && \
(head)->cqh_first->field.cqe_prev != (void *)(head)) \
panic("CIRCLEQ head forw %p %s:%d", (head), \
__FILE__, __LINE__); \
if ((head)->cqh_last != (void *)(head) && \
(head)->cqh_last->field.cqe_next != (void *)(head)) \
panic("CIRCLEQ head back %p %s:%d", (head), \
__FILE__, __LINE__);
#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
if ((elm)->field.cqe_next == (void *)(head)) { \
if ((head)->cqh_last != (elm)) \
panic("CIRCLEQ elm last %p %s:%d", (elm), \
__FILE__, __LINE__); \
} else { \
if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
panic("CIRCLEQ elm forw %p %s:%d", (elm), \
__FILE__, __LINE__); \
} \
if ((elm)->field.cqe_prev == (void *)(head)) { \
if ((head)->cqh_first != (elm)) \
panic("CIRCLEQ elm first %p %s:%d", (elm), \
__FILE__, __LINE__); \
} else { \
if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
panic("CIRCLEQ elm prev %p %s:%d", (elm), \
__FILE__, __LINE__); \
}
#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
(elm)->field.cqe_next = (void *)1L; \
(elm)->field.cqe_prev = (void *)1L;
#else
#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
#endif
#define CIRCLEQ_HEAD(name, type) \
struct name { \
struct type *cqh_first; /* first element */ \
struct type *cqh_last; /* last element */ \
}
#define CIRCLEQ_HEAD_INITIALIZER(head) \
{ (void *)&head, (void *)&head }
#define CIRCLEQ_ENTRY(type) \
struct { \
struct type *cqe_next; /* next element */ \
struct type *cqe_prev; /* previous element */ \
}
/*
* Circular queue functions.
*/
#define CIRCLEQ_INIT(head) do { \
(head)->cqh_first = (void *)(head); \
(head)->cqh_last = (void *)(head); \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
(elm)->field.cqe_prev = (listelm); \
if ((listelm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
(listelm)->field.cqe_next = (elm); \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
(elm)->field.cqe_next = (listelm); \
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
if ((listelm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
(listelm)->field.cqe_prev = (elm); \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
(elm)->field.cqe_next = (head)->cqh_first; \
(elm)->field.cqe_prev = (void *)(head); \
if ((head)->cqh_last == (void *)(head)) \
(head)->cqh_last = (elm); \
else \
(head)->cqh_first->field.cqe_prev = (elm); \
(head)->cqh_first = (elm); \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
(elm)->field.cqe_next = (void *)(head); \
(elm)->field.cqe_prev = (head)->cqh_last; \
if ((head)->cqh_first == (void *)(head)) \
(head)->cqh_first = (elm); \
else \
(head)->cqh_last->field.cqe_next = (elm); \
(head)->cqh_last = (elm); \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_REMOVE(head, elm, field) do { \
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
if ((elm)->field.cqe_next == (void *)(head)) \
(head)->cqh_last = (elm)->field.cqe_prev; \
else \
(elm)->field.cqe_next->field.cqe_prev = \
(elm)->field.cqe_prev; \
if ((elm)->field.cqe_prev == (void *)(head)) \
(head)->cqh_first = (elm)->field.cqe_next; \
else \
(elm)->field.cqe_prev->field.cqe_next = \
(elm)->field.cqe_next; \
QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
} while (/*CONSTCOND*/0)
#define CIRCLEQ_FOREACH(var, head, field) \
for ((var) = ((head)->cqh_first); \
(var) != (const void *)(head); \
(var) = ((var)->field.cqe_next))
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
for ((var) = ((head)->cqh_last); \
(var) != (const void *)(head); \
(var) = ((var)->field.cqe_prev))
/*
* Circular queue access methods.
*/
#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
(((elm)->field.cqe_next == (void *)(head)) \
? ((head)->cqh_first) \
: (elm->field.cqe_next))
#define CIRCLEQ_LOOP_PREV(head, elm, field) \
(((elm)->field.cqe_prev == (void *)(head)) \
? ((head)->cqh_last) \
: (elm->field.cqe_prev))
#endif /* !_ELF_SYS_QUEUE_H_ */
@@ -0,0 +1,29 @@
##
########################################################################################################################
#
# Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
#
########################################################################################################################
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common)
if(WIN32)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/win32)
else()
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../common/win32/sys)
endif()
add_definitions(-DBSD_LIBELF -DUSE_MEMFILE)
file(GLOB sources
${CMAKE_CURRENT_SOURCE_DIR}/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/*.c
${CMAKE_CURRENT_SOURCE_DIR}/*.h
)
add_library(oclelf STATIC ${sources})
set_target_properties(oclelf PROPERTIES POSITION_INDEPENDENT_CODE ON)
@@ -0,0 +1,12 @@
# $FreeBSD$
# $NetBSD$
libelf: a BSD-licensed implementation of the ELF(3)/GELF(3) API.
Documentation:
* Manual page elf.3 contains an overview of the library. Other
manual pages document individual APIs in the library.
* A tutorial "libelf by Example" is available at:
http://people.freebsd.org/~jkoshy/download/libelf/article.html
For ongoing development please see http://elftoolchain.sourceforge.net/
@@ -0,0 +1,64 @@
: README.build -- notes on the build process
The "Makefile" in this directory uses BSD make(1) syntax. If you are
trying to build this library on a platform that does not have a
pre-built BSD compatible make(1), then you could try porting NetBSD's
make(1). NetBSD's make(1) is available at:
http://www.crufty.net/help/sjg/bmake.html
: Supporting cross builds
In the general case, libelf may be built for a target operating system
and machine architecture that is different from the host operating
system and machine architecture that the compilation is happening on.
For example, compilation could be running on a Linux/i386 host, with
target binaries being created for a NetBSD/sparc64 system.
To support cross building:
- The top-level "Makefile" pulls in the appropriate make rules for the
target system.
Inside of makefiles, we determine the target OS by looking at the
contents of the ${unix} make variable. The top-level makefile then
includes any target specific makefiles if they exist.
- Operating systems differ in the names and locations of the headers
where their ELF types are defined. They also differ in the set of
ELF types supported. Inside of libelf's implementation these
differences are abstracted out by the auxiliary header
"_libelf_config.h".
: OS Specific Configuration :
:: Debian ::
The following packages are needed for the build:
- `build-essential'
- `m4'
- `freebsd-buildutils' or `freebsd5-buildutils'
You would need to use `freebsd-make' instead of GNU make to build
the tools. You would also need to place /usr/lib/freebsd in the
shell's `PATH', preferably at the beginning.
:: FreeBSD ::
libelf should build out of the box on FreeBSD versions later than 6.0.
:: NetBSD ::
libelf should build out of the box on NetBSD versions later than 4.0.
:: Ubuntu ::
See the section on 'Debian' above.
: Porting resources on the 'net
The 'predef' project [http://predef.sourceforge.net/] has a
comprehensive list of CPP macros predefined by various OSes.
@@ -0,0 +1,97 @@
/*
* $Id: Version.map 2033 2011-10-23 09:21:13Z jkoshy $
*
* $FreeBSD: src/lib/libelf/Version.map,v 1.3 2007/04/29 14:05:22 deischen Exp $
*/
FBSD_1.0 {
global:
elf32_checksum;
elf32_fsize;
elf32_getehdr;
elf32_getphdr;
elf32_getshdr;
elf32_newehdr;
elf32_newphdr;
elf32_xlatetof;
elf32_xlatetom;
elf64_checksum;
elf64_fsize;
elf64_getehdr;
elf64_getphdr;
elf64_getshdr;
elf64_newehdr;
elf64_newphdr;
elf64_xlatetof;
elf64_xlatetom;
elf_begin;
elf_cntl;
elf_end;
elf_errmsg;
elf_errno;
elf_fill;
elf_flagarhdr;
elf_flagdata;
elf_flagehdr;
elf_flagelf;
elf_flagphdr;
elf_flagscn;
elf_flagshdr;
elf_getarhdr;
elf_getarsym;
elf_getbase;
elf_getdata;
elf_getident;
elf_getscn;
elf_getphdrnum;
elf_getphnum;
elf_getshdrnum;
elf_getshnum;
elf_getshdrstrndx;
elf_getshstrndx;
elf_hash;
elf_kind;
elf_memory;
elf_ndxscn;
elf_newdata;
elf_newscn;
elf_next;
elf_nextscn;
elf_rand;
elf_rawdata;
elf_rawfile;
elf_setshstrndx;
elf_strptr;
elf_update;
elf_version;
gelf_checksum;
gelf_fsize;
gelf_getcap;
gelf_getclass;
gelf_getdyn;
gelf_getehdr;
gelf_getmove;
gelf_getphdr;
gelf_getrel;
gelf_getrela;
gelf_getshdr;
gelf_getsym;
gelf_getsyminfo;
gelf_getsymshndx;
gelf_newehdr;
gelf_newphdr;
gelf_update_cap;
gelf_update_dyn;
gelf_update_ehdr;
gelf_update_move;
gelf_update_phdr;
gelf_update_rel;
gelf_update_rela;
gelf_update_shdr;
gelf_update_sym;
gelf_update_syminfo;
gelf_update_symshndx;
gelf_xlatetof;
gelf_xlatetom;
local:
*;
};
@@ -0,0 +1,216 @@
/*-
* 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 1921 2011-09-23 08:04:02Z jkoshy $
*/
#ifndef __LIBELF_H_
#define __LIBELF_H_
#include <limits.h>
#include <sys/queue.h>
#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;
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_SET_ERROR(E, O) do { \
LIBELF_PRIVATE(error) = ((ELF_E_##E & LIBELF_ELF_ERROR_MASK)| \
((O) << LIBELF_OS_ERROR_SHIFT)); \
} 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 0x00FFFF /* Flags defined by the API. */
#define LIBELF_F_AR_HEADER 0x010000 /* translated header available */
#define LIBELF_F_AR_VARIANT_SVR4 0x020000 /* BSD style ar(1) archive */
#define LIBELF_F_DATA_MALLOCED 0x040000 /* whether data was malloc'ed */
#define LIBELF_F_RAWFILE_MALLOC 0x080000 /* whether e_rawfile was malloc'ed */
#define LIBELF_F_RAWFILE_MMAP 0x100000 /* whether e_rawfile was mmap'ed */
#define LIBELF_F_SHDRS_LOADED 0x200000 /* whether all shdrs were read in */
#define LIBELF_F_SPECIAL_FILE 0x400000 /* non-regular file */
struct _Elf_Mem {
void (*dealloc)(void*);
void* (*alloc)(size_t);
};
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 */
char *e_rawfile; /* uninterpreted bytes */
size_t e_rawsize; /* size of uninterpreted bytes */
unsigned int e_version; /* file version */
/* AMD Memory interface */
struct _Elf_Mem e_mem;
/*
* Header information for archive members. See the
* LIBELF_F_AR_HEADER flag.
*/
union {
Elf_Arhdr *e_arhdr; /* translated header */
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;
char *e_rawstrtab; /* file name strings */
size_t e_rawstrtabsz;
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;
};
struct _Elf_Scn {
union {
Elf32_Shdr s_shdr32;
Elf64_Shdr s_shdr64;
} s_shdr;
STAILQ_HEAD(, _Elf_Data) s_data; /* list of Elf_Data descriptors */
STAILQ_HEAD(, _Elf_Data) s_rawdata; /* raw data for this section */
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
};
#define LIBELF_COPY_U32(DST,SRC,NAME) do { \
if ((SRC)->NAME > UINT_MAX) { \
LIBELF_SET_ERROR(RANGE, 0); \
return (0); \
} \
(DST)->NAME = (SRC)->NAME; \
} while (0)
#define LIBELF_COPY_S32(DST,SRC,NAME) do { \
if ((SRC)->NAME > INT_MAX || \
(SRC)->NAME < INT_MIN) { \
LIBELF_SET_ERROR(RANGE, 0); \
return (0); \
} \
(DST)->NAME = (SRC)->NAME; \
} while (0)
/*
* Function Prototypes.
*/
__BEGIN_DECLS
Elf_Data *_libelf_allocate_data(Elf_Scn *_s);
Elf *_libelf_allocate_elf(Elf_Mem *mem);
Elf_Scn *_libelf_allocate_scn(Elf *_e, size_t _ndx);
Elf_Arhdr *_libelf_ar_gethdr(Elf *_e);
Elf *_libelf_ar_open(Elf *_e);
Elf *_libelf_ar_open_member(int _fd, Elf_Cmd _c, Elf *_ar, Elf_Mem *mem);
int _libelf_ar_get_member(char *_s, size_t _sz, int _base, size_t *_ret);
Elf_Arsym *_libelf_ar_process_bsd_symtab(Elf *_ar, size_t *_dst);
Elf_Arsym *_libelf_ar_process_svr4_symtab(Elf *_ar, size_t *_dst);
unsigned long _libelf_checksum(Elf *_e, int _elfclass);
void *_libelf_ehdr(Elf *_e, int _elfclass, int _allocate);
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))
(char *_dst, size_t dsz, 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);
int _libelf_malign(Elf_Type _t, int _elfclass);
size_t _libelf_msize(Elf_Type _t, int _elfclass, unsigned int _version);
void *_libelf_newphdr(Elf *_e, int _elfclass, size_t _count);
Elf_Data *_libelf_release_data(Elf_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
#endif /* __LIBELF_H_ */
@@ -0,0 +1,55 @@
/*-
* 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: _libelf_ar.h 2032 2011-10-23 09:07:00Z jkoshy $
*/
#ifndef __LIBELF_AR_H_
#define __LIBELF_AR_H_
/*
* Prototypes and declarations needed by libelf's ar(1) archive
* handling code.
*/
#include <ar.h>
#define LIBELF_AR_BSD_EXTENDED_NAME_PREFIX "#1/"
#define LIBELF_AR_BSD_SYMTAB_NAME "__.SYMDEF"
#define LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE \
(sizeof(LIBELF_AR_BSD_EXTENDED_NAME_PREFIX) - 1)
#define IS_EXTENDED_BSD_NAME(NAME) \
(strncmp((NAME), LIBELF_AR_BSD_EXTENDED_NAME_PREFIX, \
LIBELF_AR_BSD_EXTENDED_NAME_PREFIX_SIZE) == 0)
char *_libelf_ar_get_string(const char *_buf, size_t _sz, int _rawname,
int _svr4names);
char *_libelf_ar_get_raw_name(const struct ar_hdr *_arh);
char *_libelf_ar_get_translated_name(const struct ar_hdr *_arh, Elf *_ar);
int _libelf_ar_get_number(const char *_buf, size_t _sz, int _base,
size_t *_ret);
#endif /* __LIBELF_AR_H_ */
@@ -0,0 +1,288 @@
/*-
* 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 2032 2011-10-23 09:07:00Z jkoshy $
*/
#ifdef __FreeBSD__
#define LIBELF_VCSID(ID) __FBSDID(ID)
/*
* Define LIBELF_{ARCH,BYTEORDER,CLASS} based on the machine architecture.
* See also: <machine/elf.h>.
*/
#if defined(__amd64__)
#define LIBELF_ARCH EM_X86_64
#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__ */
#ifdef __NetBSD__
#include <machine/elf_machdep.h>
#define LIBELF_VCSID(ID) __RCSID(ID)
#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__ */
/*
* 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__) */
#define LIBELF_VCSID(ID)
#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
#define roundup2 roundup
#endif /* defined(__linux__) || defined(__GNU__) || defined(__GLIBC__) */
/*
* Common configuration for the GNU environment.
*/
#define LIBELF_CONFIG_ADDR 1
#define LIBELF_CONFIG_BYTE 1
#define LIBELF_CONFIG_DYN 1
#define LIBELF_CONFIG_EHDR 1
#define LIBELF_CONFIG_HALF 1
#define LIBELF_CONFIG_MOVEP 1
#define LIBELF_CONFIG_NOTE 1
#define LIBELF_CONFIG_OFF 1
#define LIBELF_CONFIG_PHDR 1
#define LIBELF_CONFIG_REL 1
#define LIBELF_CONFIG_RELA 1
#define LIBELF_CONFIG_SHDR 1
#define LIBELF_CONFIG_SWORD 1
#define LIBELF_CONFIG_SXWORD 1
#define LIBELF_CONFIG_SYM 1
#define LIBELF_CONFIG_VDEF 1
#define LIBELF_CONFIG_VNEED 1
#define LIBELF_CONFIG_WORD 1
#define LIBELF_CONFIG_XWORD 1
#if defined(WIN32)
#include "native-elf-format.h"
#define LIBELF_CLASS ELFTC_CLASS
#define LIBELF_ARCH ELFTC_ARCH
#define LIBELF_BYTEORDER ELFTC_BYTEORDER
#define LIBELF_CONFIG_ADDR 1
#define LIBELF_CONFIG_BYTE 1
#define LIBELF_CONFIG_DYN 1
#define LIBELF_CONFIG_EHDR 1
#define LIBELF_CONFIG_HALF 1
#define LIBELF_CONFIG_MOVEP 1
#define LIBELF_CONFIG_OFF 1
#define LIBELF_CONFIG_PHDR 1
#define LIBELF_CONFIG_REL 1
#define LIBELF_CONFIG_RELA 1
#define LIBELF_CONFIG_SHDR 1
#define LIBELF_CONFIG_SWORD 1
#define LIBELF_CONFIG_SXWORD 1
#define LIBELF_CONFIG_SYM 1
#define LIBELF_CONFIG_WORD 1
#define LIBELF_CONFIG_XWORD 1
#define LIBELF_VCSID(ID)
#define roundup2 roundup
#endif // defined(WIN32)
#ifndef LIBELF_CONFIG_GNUHASH
#define LIBELF_CONFIG_GNUHASH 1
/*
* The header for GNU-style hash sections.
*/
typedef struct {
u_int32_t gh_nbuckets; /* Number of hash buckets. */
u_int32_t gh_symndx; /* First visible symbol in .dynsym. */
u_int32_t gh_maskwords; /* #maskwords used in bloom filter. */
u_int32_t gh_shift2; /* Bloom filter shift count. */
} Elf_GNU_Hash_Header;
#endif
#if defined(USE_MEMFILE)
#include "memfile.h"
#if !defined(read)
#define read(f, b, l) mem_read((f), (b), (l))
#endif
#if !defined(write)
#define write(f, b, l) mem_write((f), (b), (l))
#endif
#if !defined(lseek)
#define lseek(f, l, w) mem_lseek((f), (l), (w))
#endif
#if !defined(fstat)
#define fstat(f, b) mem_fstat((f), (struct stat*)(b))
#endif
#if !defined(_fstat64i32)
#define _fstat64i32(f, b) mem_fstat((f), (struct stat*)(b))
#endif
#if !defined(_fstat32i64)
#define _fstat32i64(f, b) mem_fstat((f), (struct stat*)(b))
#endif
#if !defined(_fstat32)
#define _fstat32(f, b) mem_fstat((f), (struct stat*)(b))
#endif
#if !defined(_fstat64)
#define _fstat64(f, b) mem_fstat((f), (struct stat*)(b))
#endif
#if !defined(ftruncate)
#define ftruncate(f, l) mem_ftruncate((f), (size_t)(l))
#endif
#if !defined(_chsize)
#define _chsize(f, l) mem_ftruncate((f), (size_t)(l))
#endif
#if !defined(mmap)
#define mmap mem_mmap
#endif
#if !defined(mem_munmap)
#define munmap mem_munmap
#endif
#else // !USE_MEMFILE
#if !defined(mmap)
#if defined(WIN32)
#define mmap w32_mmap
#else
#define mmap mmap
#endif
#endif
#if !defined(mem_munmap)
#if defined(WIN32)
#define munmap w32_munmap
#else
#define munmap munmap
#endif
#endif
#endif //USE_MEMFILE
@@ -0,0 +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 <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf.c 1345 2011-01-01 11:17:52Z jkoshy $");
struct _libelf_globals _libelf = {
/*.libelf_arch = */LIBELF_ARCH,
/*.libelf_byteorder = */LIBELF_BYTEORDER,
/*.libelf_class = */LIBELF_CLASS,
/*.libelf_error = */0,
/*.libelf_fillchar = */0,
/*.libelf_version = */EV_NONE,
{ 0 }
};
@@ -0,0 +1,334 @@
/*-
* 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 <sys/cdefs.h>
#include <sys/types.h>
#if !defined(WIN32)
#include <sys/errno.h>
#include <sys/mman.h>
#else
#ifndef PROT_READ
#define PROT_READ FILE_MAP_READ
#endif
#ifndef MAP_PRIVATE
#define MAP_PRIVATE FILE_MAP_COPY
#endif
#ifndef MAP_FAILED
#define MAP_FAILED NULL
#endif
#include <Windows.h>
#endif
#include <sys/stat.h>
#include <ar.h>
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <libelf.h>
#include <stdlib.h>
#include <stdio.h>
#if !defined(WIN32)
#include <unistd.h>
#else
#include "compat.h"
#endif
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_begin.c 1923 2011-09-23 09:01:13Z jkoshy $");
#define _LIBELF_INITSIZE (64*1024)
/*
* Read from a device file, pipe or socket.
*/
static void *
_libelf_read_special_file(int fd, size_t *fsz)
{
ssize_t readsz;
size_t bufsz, datasz;
unsigned char *buf, *t;
datasz = 0;
readsz = 0;
bufsz = _LIBELF_INITSIZE;
if ((buf = malloc(bufsz)) == NULL)
goto resourceerror;
/*
* Read data from the file descriptor till we reach EOF, or
* till an error is encountered.
*/
do {
/* Check if we need to expand the data buffer. */
if (datasz == bufsz) {
bufsz *= 2;
if ((t = realloc(buf, bufsz)) == NULL)
goto resourceerror;
buf = t;
}
do {
readsz = bufsz - datasz;
t = buf + datasz;
if ((readsz = read(fd, t, readsz)) <= 0)
break;
datasz += readsz;
} while (datasz < bufsz);
} while (readsz > 0);
if (readsz < 0) {
LIBELF_SET_ERROR(IO, errno);
goto error;
}
assert(readsz == 0);
/*
* Free up extra buffer space.
*/
if (bufsz > datasz) {
if (datasz > 0) {
if ((t = realloc(buf, datasz)) == NULL)
goto resourceerror;
buf = t;
} else { /* Zero bytes read. */
LIBELF_SET_ERROR(ARGUMENT, 0);
free(buf);
buf = NULL;
}
}
*fsz = datasz;
return (buf);
resourceerror:
LIBELF_SET_ERROR(RESOURCE, 0);
error:
if (buf != NULL)
free(buf);
return (NULL);
}
static Elf *
_libelf_open_object(int fd, Elf_Cmd c, Elf_Mem *mem)
{
Elf *e;
void *m;
mode_t mode;
size_t fsize;
struct stat sb;
unsigned int flags;
assert(c == ELF_C_READ || c == ELF_C_RDWR || c == ELF_C_WRITE);
if (fstat(fd, &sb) < 0) {
LIBELF_SET_ERROR(IO, errno);
return (NULL);
}
mode = sb.st_mode;
fsize = (size_t) sb.st_size;
/*
* Reject unsupported file types.
*/
if (!S_ISREG(mode) && !S_ISCHR(mode)
#if !defined(WIN32)
&& !S_ISFIFO(mode) &&
!S_ISSOCK(mode)
#endif
) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
/*
* For ELF_C_WRITE mode, allocate and return a descriptor.
* For ELF_C_RDWR mode, if the file is empty, allocate and return.
*/
if (c == ELF_C_WRITE || (c == ELF_C_RDWR && !fsize)) {
if ((e = _libelf_allocate_elf(mem)) != NULL) {
_libelf_init_elf(e, ELF_K_ELF);
e->e_byteorder = LIBELF_PRIVATE(byteorder);
e->e_fd = fd;
e->e_cmd = c;
if (!S_ISREG(mode))
e->e_flags |= LIBELF_F_SPECIAL_FILE;
}
return (e);
}
/*
* ELF_C_READ and ELF_C_RDWR mode.
*/
m = NULL;
flags = 0;
if (S_ISREG(mode)) {
/*
* Always map regular files in with 'PROT_READ'
* permissions.
*
* For objects opened in ELF_C_RDWR mode, when
* elf_update(3) is called, we remove this mapping,
* write file data out using write(2), and map the new
* contents back.
*/
if ((m = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd,
(off_t) 0)) == MAP_FAILED) {
LIBELF_SET_ERROR(IO, errno);
return (NULL);
}
flags = LIBELF_F_RAWFILE_MMAP;
#if 0
m = mem.alloc(fsize);
if (!fread(m, 1, fsize, _fdopen(fd, "w+b"))) {
LIBELF_SET_ERROR(IO, errno);
mem.dealloc(m);
return(NULL);
}
flags = LIBELF_F_RAWFILE_MALLOC;
#endif
} else if ((m = _libelf_read_special_file(fd, &fsize)) != NULL)
flags = LIBELF_F_RAWFILE_MALLOC | LIBELF_F_SPECIAL_FILE;
else
return (NULL);
if ((e = elf_memory(m, fsize, mem)) == NULL) {
assert((flags & LIBELF_F_RAWFILE_MALLOC) ||
(flags & LIBELF_F_RAWFILE_MMAP));
if (flags & LIBELF_F_RAWFILE_MMAP)
(void) munmap(m, fsize);
else
e->e_mem.dealloc(m);
return (NULL);
}
/* ar(1) archives aren't supported in RDWR mode. */
if (c == ELF_C_RDWR && e->e_kind == ELF_K_AR) {
(void) elf_end(e);
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
e->e_flags |= flags;
e->e_fd = fd;
e->e_cmd = c;
return (e);
}
Elf *
elf_begin(int fd, Elf_Cmd c, Elf *a, Elf_Mem *mem)
{
Elf *e;
e = NULL;
if (LIBELF_PRIVATE(version) == EV_NONE) {
LIBELF_SET_ERROR(SEQUENCE, 0);
return (NULL);
}
switch (c) {
case ELF_C_NULL:
return (NULL);
case ELF_C_WRITE:
/*
* The ELF_C_WRITE command is required to ignore the
* descriptor passed in.
*/
a = NULL;
break;
case ELF_C_RDWR:
if (a != NULL && a->e_kind == ELF_K_AR) { /* not allowed for ar(1) archives. */
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
/*FALLTHROUGH*/
case ELF_C_READ:
/*
* Descriptor `a' could be for a regular ELF file, or
* for an ar(1) archive. If descriptor `a' was opened
* using a valid file descriptor, we need to check if
* the passed in `fd' value matches the original one.
*/
if (a &&
((a->e_fd != -1 && a->e_fd != fd) || c != a->e_cmd)) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
break;
default:
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (a == NULL)
e = _libelf_open_object(fd, c, mem);
else if (a->e_kind == ELF_K_AR)
e = _libelf_ar_open_member(a->e_fd, c, a, mem);
else
(e = a)->e_activations++;
return (e);
}
#if defined(WIN32)
// This code taken from:
// http://git.661346.n2.nabble.com/PATCH-mmap-implementation-for-mingw-td1560056.html
// This code is in public domain according to the FAQ here:
// http://www.mingw.org/wiki/FAQ
// http://www.mingw.org/license
// FIXME: This needs to be more robust to the protection and flag options.
void *w32_mmap(void *start, size_t length, int prot, int flags, int fd,
unsigned offset)
{
HANDLE handle;
if (start != NULL || !(flags & MAP_PRIVATE))
assert(!"Invalid usage of mingw_mmap");
handle = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, PAGE_READONLY, 0, 0, NULL);
if (handle != NULL) {
start = MapViewOfFile(handle, flags, 0, offset,
length);
CloseHandle(handle);
}
return start;
}
int w32_munmap(void *start, size_t length) {
UnmapViewOfFile(start);
return 0;
}
#endif
@@ -0,0 +1,58 @@
/*-
* 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 <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_cntl.c 189 2008-07-20 10:38:08Z jkoshy $");
int
elf_cntl(Elf *e, Elf_Cmd c)
{
if (e == NULL ||
(c != ELF_C_FDDONE && c != ELF_C_FDREAD)) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (-1);
}
if (e->e_parent) {
LIBELF_SET_ERROR(ARCHIVE, 0);
return (-1);
}
if (c == ELF_C_FDREAD) {
if (e->e_cmd == ELF_C_WRITE) {
LIBELF_SET_ERROR(MODE, 0);
return (-1);
}
else
return (0);
}
e->e_fd = -1;
return 0;
}
@@ -0,0 +1,254 @@
/*-
* 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 <assert.h>
#include <errno.h>
#include <libelf.h>
#include <stdlib.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_data.c 1765 2011-08-22 05:59:05Z jkoshy $");
Elf_Data *
elf_getdata(Elf_Scn *s, Elf_Data *d)
{
Elf *e;
size_t fsz, msz, count;
int elfclass, elftype;
unsigned int sh_type;
uint64_t sh_align, sh_offset, sh_size;
int (*xlate)(char *_d, size_t _dsz, char *_s, size_t _c, int _swap);
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);
if (d != NULL)
return (STAILQ_NEXT(d, d_next));
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);
}
count = sh_size / fsz;
msz = _libelf_msize(elftype, elfclass, e->e_version);
assert(msz > 0);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_buf = NULL;
d->d_off = 0;
d->d_align = sh_align;
d->d_size = msz * count;
d->d_type = elftype;
d->d_version = e->e_version;
if (sh_type == SHT_NOBITS || sh_size == 0) {
STAILQ_INSERT_TAIL(&s->s_data, d, d_next);
return (d);
}
if ((d->d_buf = e->e_mem.alloc(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_buf, d->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);
}
Elf_Data *
elf_newdata(Elf_Scn *s)
{
Elf *e;
Elf_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_align = 1;
d->d_buf = NULL;
d->d_off = (uint64_t) ~0;
d->d_size = 0;
d->d_type = ELF_T_BYTE;
d->d_version = LIBELF_PRIVATE(version);
(void) elf_flagscn(s, ELF_C_SET, ELF_F_DIRTY);
return (d);
}
/*
* Retrieve a data descriptor for raw (untranslated) data for section
* `s'.
*/
Elf_Data *
elf_rawdata(Elf_Scn *s, Elf_Data *d)
{
Elf *e;
int elf_class;
uint32_t sh_type;
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);
if (d == NULL && (d = STAILQ_FIRST(&s->s_rawdata)) != NULL)
return (d);
if (d != NULL)
return (STAILQ_NEXT(d, d_next));
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)
return (NULL);
if ((d = _libelf_allocate_data(s)) == NULL)
return (NULL);
d->d_buf = (sh_type == SHT_NOBITS || sh_size == 0) ? NULL :
e->e_rawfile + sh_offset;
d->d_off = 0;
d->d_align = sh_align;
d->d_size = sh_size;
d->d_type = ELF_T_BYTE;
d->d_version = e->e_version;
STAILQ_INSERT_TAIL(&s->s_rawdata, d, d_next);
return (d);
}
void
elf_removedata(Elf_Scn *s, Elf_Data *d)
{
STAILQ_REMOVE(&s->s_data, d, _Elf_Data, d_next);
d = _libelf_release_data(d);
}
@@ -0,0 +1,99 @@
/*-
* 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 <sys/cdefs.h>
#if !defined(WIN32)
#include <sys/mman.h>
#endif
#include <assert.h>
#include <libelf.h>
#include <stdlib.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_end.c 1922 2011-09-23 08:04:33Z jkoshy $");
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_MMAP)
#if !defined(WIN32)
(void) munmap(e->e_rawfile, e->e_rawsize);
#else
abort();
#endif
else if (e->e_flags & LIBELF_F_RAWFILE_MALLOC)
e->e_mem.dealloc(e->e_rawfile);
}
sv = e;
if ((e = e->e_parent) != NULL)
e->e_u.e_ar.e_nchildren--;
sv = _libelf_release_elf(sv);
}
return (0);
}
@@ -0,0 +1,88 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include <stdio.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_errmsg.c 1345 2011-01-01 11:17:52Z jkoshy $");
/*
* Retrieve a human readable translation for an error message.
*/
#if defined(__GNUC__)
#define DEFINE_ERROR(N,S) [ELF_E_##N] = S
#else
#define DEFINE_ERROR(N,S) S
#endif
const char *_libelf_errors[] = {
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(LIBELF_PRIVATE(msg),
sizeof(LIBELF_PRIVATE(msg)), "%s: %s",
_libelf_errors[error], strerror(oserr));
return (const char *)&LIBELF_PRIVATE(msg);
}
return _libelf_errors[error];
}
@@ -0,0 +1,43 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_errno.c 1345 2011-01-01 11:17:52Z jkoshy $");
int
elf_errno(void)
{
int old;
old = LIBELF_PRIVATE(error);
LIBELF_PRIVATE(error) = 0;
return (old & LIBELF_ELF_ERROR_MASK);
}
@@ -0,0 +1,39 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_fill.c 189 2008-07-20 10:38:08Z jkoshy $");
void
elf_fill(int fill)
{
LIBELF_PRIVATE(fillchar) = fill;
}
@@ -0,0 +1,195 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_flag.c 1918 2011-09-22 10:42:06Z jkoshy $");
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;
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);
}
if (c == ELF_C_SET)
r = d->d_flags |= flags;
else
r = d->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)
{
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)
{
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));
}
@@ -0,0 +1,47 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_getarhdr.c 1341 2011-01-01 04:28:29Z jkoshy $");
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));
}
@@ -0,0 +1,58 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_getarsym.c 1360 2011-01-08 08:27:41Z jkoshy $");
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);
}
@@ -0,0 +1,48 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_getbase.c 977 2010-06-06 11:50:31Z jkoshy $");
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));
}
@@ -0,0 +1,68 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <assert.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_getident.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf_config.h"
LIBELF_VCSID("$Id: elf_hash.c 189 2008-07-20 10:38:08Z jkoshy $");
/*
* 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);
}
@@ -0,0 +1,44 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_kind.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +1,92 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <libelf.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_memory.c 189 2008-07-20 10:38:08Z jkoshy $");
Elf *
elf_memory(char *image, size_t sz, Elf_Mem *mem)
{
Elf *e;
if (LIBELF_PRIVATE(version) == EV_NONE) {
LIBELF_SET_ERROR(SEQUENCE, 0);
return (NULL);
}
if (image == NULL || sz == 0) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if ((e = _libelf_allocate_elf(mem)) == NULL)
return (NULL);
e->e_cmd = ELF_C_READ;
e->e_rawfile = image;
e->e_rawsize = sz;
#undef LIBELF_IS_ELF
#define LIBELF_IS_ELF(P) ((P)[EI_MAG0] == ELFMAG0 && \
(P)[EI_MAG1] == ELFMAG1 && (P)[EI_MAG2] == ELFMAG2 && \
(P)[EI_MAG3] == ELFMAG3)
if (sz > EI_NIDENT && LIBELF_IS_ELF(image)) {
_libelf_init_elf(e, ELF_K_ELF);
e->e_class = image[EI_CLASS];
e->e_byteorder = image[EI_DATA];
e->e_version = image[EI_VERSION];
if (e->e_version > EV_CURRENT) {
e = _libelf_release_elf(e);
LIBELF_SET_ERROR(VERSION, 0);
return (NULL);
}
if ((e->e_byteorder != ELFDATA2LSB && e->e_byteorder !=
ELFDATA2MSB) || (e->e_class != ELFCLASS32 && e->e_class !=
ELFCLASS64)) {
e = _libelf_release_elf(e);
LIBELF_SET_ERROR(HEADER, 0);
return (NULL);
}
} else if (sz >= SARMAG &&
strncmp(image, ARMAG, (size_t) SARMAG) == 0) {
_libelf_init_elf(e, ELF_K_AR);
e = _libelf_ar_open(e);
} else
_libelf_init_elf(e, ELF_K_NONE);
return (e);
}
@@ -0,0 +1,62 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <assert.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_next.c 1678 2011-07-28 04:36:34Z jkoshy $");
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 + e->e_rawsize;
next = (next + 1) & ~1; /* round up to an even boundary */
parent->e_u.e_ar.e_next = (next >= (off_t) parent->e_rawsize) ?
(off_t) 0 : next;
return (ELF_C_READ);
}
@@ -0,0 +1,67 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_phnum.c 466 2009-08-04 17:17:42Z jkoshy $");
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);
}
@@ -0,0 +1,59 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_rand.c 189 2008-07-20 10:38:08Z jkoshy $");
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 ||
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);
}
@@ -0,0 +1,53 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_rawfile.c 189 2008-07-20 10:38:08Z jkoshy $");
char *
elf_rawfile(Elf *e, size_t *sz)
{
char *ptr;
size_t size;
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 (ptr);
}
@@ -0,0 +1,245 @@
/*-
* 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 <sys/cdefs.h>
#include <sys/queue.h>
#include <assert.h>
#include <errno.h>
#include <gelf.h>
#include <libelf.h>
#include <stddef.h>
#include <stdlib.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_scn.c 1077 2010-08-09 15:37:40Z jkoshy $");
/*
* Load an ELF section table and create a list of Elf_Scn structures.
*/
int
_libelf_load_section_headers(Elf *e, void *ehdr)
{
int ec, swapbytes;
size_t fsz, i, shnum;
uint64_t shoff;
char *src;
Elf32_Ehdr *eh32;
Elf64_Ehdr *eh64;
Elf_Scn *scn;
int (*xlator)(char *_d, size_t _dsz, 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 (fsz != (EH)->e_shentsize || \
(e->e_rawfile && shoff + fsz * shnum > e->e_rawsize)) { \
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);
// If we aren't editing a rawfile, then we don't need to
// load any sections.
if (!e->e_rawfile) {
return 1;
}
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)((char *) &scn->s_shdr, sizeof(scn->s_shdr), src,
(size_t) 1, swapbytes);
if (ec == ELFCLASS32) {
scn->s_offset =
scn->s_shdr.s_shdr32.sh_offset;
scn->s_size = scn->s_shdr.s_shdr32.sh_size;
} else {
scn->s_offset =
scn->s_shdr.s_shdr64.sh_offset;
scn->s_size = scn->s_shdr.s_shdr64.sh_size;
}
// If we have a true read/write elf, we cannot trust the
// raw offset and we need to pull in the data also when
// the section headers are loaded.
if (e->e_cmd != ELF_C_RDWR) {
scn->s_rawoff = scn->s_offset;
} else {
elf_getdata(scn, NULL);
}
}
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));
}
@@ -0,0 +1,67 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_shnum.c 466 2009-08-04 17:17:42Z jkoshy $");
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);
}
@@ -0,0 +1,82 @@
/*-
* 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 <sys/cdefs.h>
#include <ar.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_shstrndx.c 466 2009-08-04 17:17:42Z jkoshy $");
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));
}
@@ -0,0 +1,136 @@
/*-
* 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 <assert.h>
#include <gelf.h>
#include "_libelf.h"
#ifdef ANDROID
#include "roundup.h"
#else
#include <sys/param.h>
#endif
LIBELF_VCSID("$Id: elf_strptr.c 189 2008-07-20 10:38:08Z jkoshy $");
/*
* Convert an ELF section#,offset pair to a string pointer.
*/
char *
elf_strptr(Elf *e, size_t scndx, size_t offset)
{
Elf_Scn *s;
Elf_Data *d;
size_t alignment, count;
GElf_Shdr shdr;
if (e == NULL || e->e_kind != ELF_K_ELF) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if ((s = elf_getscn(e, scndx)) == NULL ||
gelf_getshdr(s, &shdr) == NULL)
return (NULL);
if (shdr.sh_type != SHT_STRTAB ||
offset >= shdr.sh_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
d = NULL;
if (e->e_flags & ELF_F_LAYOUT) {
/*
* The application is taking responsibility for the
* ELF object's layout, so we can directly translate
* an offset to a `char *' address using the `d_off'
* members of Elf_Data descriptors.
*/
while ((d = elf_getdata(s, d)) != NULL) {
if (d->d_buf == 0 || d->d_size == 0)
continue;
if (d->d_type != ELF_T_BYTE) {
LIBELF_SET_ERROR(DATA, 0);
return (NULL);
}
if (offset >= d->d_off &&
offset < d->d_off + d->d_size)
return ((char *) d->d_buf + offset - d->d_off);
}
} else {
/*
* Otherwise, the `d_off' members are not useable and
* we need to compute offsets ourselves, taking into
* account 'holes' in coverage of the section introduced
* by alignment requirements.
*/
count = (size_t) 0; /* cumulative count of bytes seen */
while ((d = elf_getdata(s, d)) != NULL && count <= offset) {
if (d->d_buf == NULL || d->d_size == 0)
continue;
if (d->d_type != ELF_T_BYTE) {
LIBELF_SET_ERROR(DATA, 0);
return (NULL);
}
if ((alignment = d->d_align) > 1) {
if ((alignment & (alignment - 1)) != 0) {
LIBELF_SET_ERROR(DATA, 0);
return (NULL);
}
count = roundup2(count, alignment);
}
if (offset < count) {
/* offset starts in the 'hole' */
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (offset < count + d->d_size) {
if (d->d_buf != NULL)
return ((char *) d->d_buf +
offset - count);
LIBELF_SET_ERROR(DATA, 0);
return (NULL);
}
count += d->d_size;
}
}
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
@@ -0,0 +1,52 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: elf_version.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +1,114 @@
/*-
* 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 $
*/
#ifndef _GELF_H_
#define _GELF_H_
#include <sys/cdefs.h>
#include <libelf.h>
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 */
#if (defined(__FreeBSD_version) && __FreeBSD_version >= 700025) || \
(defined(__NetBSD_Version) && __NetBSD_Version > 400000003)
typedef Elf64_Cap GElf_Cap; /* SW/HW capabilities */
typedef Elf64_Move GElf_Move; /* Move entries */
typedef Elf64_Syminfo GElf_Syminfo; /* Symbol information */
#endif
#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
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);
#if (defined(__FreeBSD_version) && __FreeBSD_version >= 700025) || \
(defined(__NetBSD_Version) && __NetBSD_Version > 400000003)
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);
#endif
__END_DECLS
#endif /* _GELF_H_ */
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_cap.c 1166 2010-09-04 00:54:36Z jkoshy $");
#if LIBELF_CONFIG_CAP
GElf_Cap *
gelf_getcap(Elf_Data *d, int ndx, GElf_Cap *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Cap *cap32;
Elf64_Cap *cap64;
size_t msz;
uint32_t sh_type;
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 * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
cap32 = (Elf32_Cap *) d->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_buf + ndx;
*dst = *cap64;
}
return (dst);
}
int
gelf_update_cap(Elf_Data *d, int ndx, GElf_Cap *gc)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Cap *cap32;
Elf64_Cap *cap64;
size_t msz;
uint32_t sh_type;
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 * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
cap32 = (Elf32_Cap *) d->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_buf + ndx;
*cap64 = *gc;
}
return (1);
}
#endif /* LIBELF_CONFIG_CAP */
@@ -0,0 +1,58 @@
/*-
* 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 <sys/cdefs.h>
#include <gelf.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_checksum.c 189 2008-07-20 10:38:08Z jkoshy $");
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));
}
@@ -0,0 +1,143 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_dyn.c 189 2008-07-20 10:38:08Z jkoshy $");
GElf_Dyn *
gelf_getdyn(Elf_Data *d, int ndx, GElf_Dyn *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Dyn *dyn32;
Elf64_Dyn *dyn64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
dyn32 = (Elf32_Dyn *) d->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_buf + ndx;
*dst = *dyn64;
}
return (dst);
}
int
gelf_update_dyn(Elf_Data *d, int ndx, GElf_Dyn *ds)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Dyn *dyn32;
Elf64_Dyn *dyn64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
dyn32 = (Elf32_Dyn *) d->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_buf + ndx;
*dyn64 = *ds;
}
return (1);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include <libelf.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_ehdr.c 1678 2011-07-28 04:36:34Z jkoshy $");
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);
}
@@ -0,0 +1,62 @@
/*-
* 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 <sys/cdefs.h>
#include <gelf.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_fsize.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +1,39 @@
/*-
* 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 <sys/cdefs.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_getclass.c 189 2008-07-20 10:38:08Z jkoshy $");
int
gelf_getclass(Elf *e)
{
return (e != NULL ? e->e_class : ELFCLASSNONE);
}
@@ -0,0 +1,154 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_move.c 1166 2010-09-04 00:54:36Z jkoshy $");
#if LIBELF_CONFIG_MOVE
GElf_Move *
gelf_getmove(Elf_Data *d, int ndx, GElf_Move *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Move *move32;
Elf64_Move *move64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
move32 = (Elf32_Move *) d->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_buf + ndx;
*dst = *move64;
}
return (dst);
}
int
gelf_update_move(Elf_Data *d, int ndx, GElf_Move *gm)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Move *move32;
Elf64_Move *move64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
move32 = (Elf32_Move *) d->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_buf + ndx;
*move64 = *gm;
}
return (1);
}
#endif /* LIBELF_CONFIG_MOVE */
@@ -0,0 +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 <sys/cdefs.h>
#include <gelf.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_phdr.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_rel.c 189 2008-07-20 10:38:08Z jkoshy $");
GElf_Rel *
gelf_getrel(Elf_Data *d, int ndx, GElf_Rel *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Rel *rel32;
Elf64_Rel *rel64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
rel32 = (Elf32_Rel *) d->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_buf + ndx;
*dst = *rel64;
}
return (dst);
}
int
gelf_update_rel(Elf_Data *d, int ndx, GElf_Rel *dr)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Rel *rel32;
Elf64_Rel *rel64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
rel32 = (Elf32_Rel *) d->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(ELF64_R_SYM(dr->r_info),
ELF64_R_TYPE(dr->r_info));
} else {
rel64 = (Elf64_Rel *) d->d_buf + ndx;
*rel64 = *dr;
}
return (1);
}
@@ -0,0 +1,155 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_rela.c 189 2008-07-20 10:38:08Z jkoshy $");
GElf_Rela *
gelf_getrela(Elf_Data *d, int ndx, GElf_Rela *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Rela *rela32;
Elf64_Rela *rela64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
rela32 = (Elf32_Rela *) d->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_buf + ndx;
*dst = *rela64;
}
return (dst);
}
int
gelf_update_rela(Elf_Data *d, int ndx, GElf_Rela *dr)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Rela *rela32;
Elf64_Rela *rela64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
rela32 = (Elf32_Rela *) d->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(ELF64_R_SYM(dr->r_info),
ELF64_R_TYPE(dr->r_info));
LIBELF_COPY_S32(rela32, dr, r_addend);
} else {
rela64 = (Elf64_Rela *) d->d_buf + ndx;
*rela64 = *dr;
}
return (1);
}
@@ -0,0 +1,129 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_shdr.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_sym.c 189 2008-07-20 10:38:08Z jkoshy $");
GElf_Sym *
gelf_getsym(Elf_Data *d, int ndx, GElf_Sym *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Sym *sym32;
Elf64_Sym *sym64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
sym32 = (Elf32_Sym *) d->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 = ELF64_ST_INFO(ELF32_ST_BIND(sym32->st_info),
ELF32_ST_TYPE(sym32->st_info));
dst->st_other = sym32->st_other;
dst->st_shndx = sym32->st_shndx;
} else {
sym64 = (Elf64_Sym *) d->d_buf + ndx;
*dst = *sym64;
}
return (dst);
}
int
gelf_update_sym(Elf_Data *d, int ndx, GElf_Sym *gs)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Sym *sym32;
Elf64_Sym *sym64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
sym32 = (Elf32_Sym *) d->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_buf + ndx;
*sym64 = *gs;
}
return (1);
}
@@ -0,0 +1,147 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_syminfo.c 1166 2010-09-04 00:54:36Z jkoshy $");
#if LIBELF_CONFIG_SYMINFO
GElf_Syminfo *
gelf_getsyminfo(Elf_Data *d, int ndx, GElf_Syminfo *dst)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Syminfo *syminfo32;
Elf64_Syminfo *syminfo64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (NULL);
}
if (ec == ELFCLASS32) {
syminfo32 = (Elf32_Syminfo *) d->d_buf + ndx;
dst->si_boundto = syminfo32->si_boundto;
dst->si_flags = syminfo32->si_flags;
} else {
syminfo64 = (Elf64_Syminfo *) d->d_buf + ndx;
*dst = *syminfo64;
}
return (dst);
}
int
gelf_update_syminfo(Elf_Data *d, int ndx, GElf_Syminfo *gs)
{
int ec;
Elf *e;
Elf_Scn *scn;
Elf32_Syminfo *syminfo32;
Elf64_Syminfo *syminfo64;
size_t msz;
uint32_t sh_type;
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);
if (msz * ndx >= d->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
if (ec == ELFCLASS32) {
syminfo32 = (Elf32_Syminfo *) d->d_buf + ndx;
syminfo32->si_boundto = gs->si_boundto;
syminfo32->si_flags = gs->si_flags;
} else {
syminfo64 = (Elf64_Syminfo *) d->d_buf + ndx;
*syminfo64 = *gs;
}
return (1);
}
#endif /* LIBELF_CONFIG_SYMINFO */
@@ -0,0 +1,128 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_symshndx.c 189 2008-07-20 10:38:08Z jkoshy $");
GElf_Sym *
gelf_getsymshndx(Elf_Data *d, Elf_Data *id, int ndx, GElf_Sym *dst,
Elf32_Word *shindex)
{
int ec;
Elf *e;
Elf_Scn *scn;
size_t msz;
uint32_t sh_type;
if (gelf_getsym(d, ndx, dst) == 0)
return (NULL);
if (id == NULL || (scn = id->d_scn) == NULL ||
(e = scn->s_elf) == NULL || (e != d->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);
if (msz * 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;
Elf_Scn *scn;
size_t msz;
uint32_t sh_type;
if (gelf_update_sym(d, ndx, gs) == 0)
return (0);
if (id == NULL || (scn = id->d_scn) == NULL ||
(e = scn->s_elf) == NULL || (e != d->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);
if (msz * ndx >= id->d_size) {
LIBELF_SET_ERROR(ARGUMENT, 0);
return (0);
}
*(((Elf32_Word *) id->d_buf) + ndx) = xindex;
return (1);
}
@@ -0,0 +1,81 @@
/*-
* 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 <sys/cdefs.h>
#include <gelf.h>
#include <libelf.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: gelf_xlate.c 1678 2011-07-28 04:36:34Z jkoshy $");
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);
}
@@ -0,0 +1,262 @@
/*-
* 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 1345 2011-01-01 11:17:52Z jkoshy $
*/
#ifndef _LIBELF_H_
#define _LIBELF_H_
#include <sys/types.h>
#include <sys/queue.h>
#include <elfdefinitions.h>
#ifndef EM_HSAIL
#define EM_HSAIL 0xAF5A
#endif
/* Library private data structures */
typedef struct _Elf Elf;
typedef struct _Elf_Scn Elf_Scn;
typedef struct _Elf_Mem Elf_Mem;
/* 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;
/*
* Members that are not part of the public API.
*/
Elf_Scn *d_scn; /* containing section */
unsigned int d_flags;
STAILQ_ENTRY(_Elf_Data) d_next;
} 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.
*/
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
Elf *elf_begin(int _fd, Elf_Cmd _cmd, Elf *_elf, Elf_Mem *_mem);
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 *);
void elf_removedata(Elf_Scn *s, Elf_Data *d);
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, Elf_Mem *mem);
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);
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
#endif /* _LIBELF_H_ */
@@ -0,0 +1,185 @@
/*-
* 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 <sys/cdefs.h>
#include <sys/types.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_align.c 1169 2010-09-04 01:06:31Z jkoshy $");
struct align {
int a32;
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) \
}
#elif !defined(_MSC_VER)
#error Need the __alignof__ builtin.
#endif
#define UNSUPPORTED() { \
.a32 = 0, \
.a64 = 0 \
}
static struct align malign[ELF_T_NUM] = {
#if defined(__GNUC__)
[ELF_T_ADDR] = MALIGN(Addr),
[ELF_T_BYTE] = { .a32 = 1, .a64 = 1 },
#if LIBELF_CONFIG_CAP
[ELF_T_CAP] = MALIGN(Cap),
#endif
[ELF_T_DYN] = MALIGN(Dyn),
[ELF_T_EHDR] = MALIGN(Ehdr),
[ELF_T_HALF] = MALIGN(Half),
#if LIBELF_CONFIG_LWORD
[ELF_T_LWORD] = MALIGN(Lword),
#endif
#if LIBELF_CONFIG_MOVE
[ELF_T_MOVE] = MALIGN(Move),
#endif
[ELF_T_MOVEP] = UNSUPPORTED(),
#if LIBELF_CONFIG_NOTE
[ELF_T_NOTE] = MALIGN(Nhdr),
#endif
[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),
#if LIBELF_CONFIG_SYMINFO
[ELF_T_SYMINFO] = MALIGN(Syminfo),
#endif
#if LIBELF_CONFIG_VDEF
[ELF_T_VDEF] = MALIGN(Verdef),
#endif
#if LIBELF_CONFIG_VNEED
[ELF_T_VNEED] = MALIGN(Verneed),
#endif
[ELF_T_WORD] = MALIGN(Word),
[ELF_T_XWORD] = MALIGN64(Xword),
[ELF_T_GNUHASH] = MALIGN_WORD()
#elif defined(_MSC_VER)
{ 4, 8 }, { 1, 1 }, { 4, 8 }, { 4, 8 }, { 4, 8 },
{ 2, 2 }, { 8, 8 }, { 8, 8 }, { 0, 0 }, { 4, 4 },
{ 4, 8 }, { 4, 8 }, { 4, 8 }, { 4, 8 }, { 4, 8 },
{ 4, 4 }, { 0, 8 }, { 4, 8 }, { 2, 2 }, { 4, 4 },
{ 4, 4 }, { 4, 4 }, { 0, 8 }, { 4, 8 }
#else
#error
#endif
};
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] = {
#if defined(__GNUC__)
[ELF_T_ADDR] = FALIGN(4,8),
[ELF_T_BYTE] = FALIGN(1,1),
#if LIBELF_CONFIG_CAP
[ELF_T_CAP] = FALIGN(4,8),
#endif
[ELF_T_DYN] = FALIGN(4,8),
[ELF_T_EHDR] = FALIGN(4,8),
[ELF_T_HALF] = FALIGN(2,2),
#if LIBELF_CONFIG_LWORD
[ELF_T_LWORD] = FALIGN(8,8),
#endif
#if LIBELF_CONFIG_MOVE
[ELF_T_MOVE] = FALIGN(8,8),
#endif
[ELF_T_MOVEP] = UNSUPPORTED(),
#if LIBELF_CONFIG_NOTE
[ELF_T_NOTE] = FALIGN(4,4),
#endif
[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),
#if LIBELF_CONFIG_SYMINFO
[ELF_T_SYMINFO] = FALIGN(2,2),
#endif
#if LIBELF_CONFIG_VDEF
[ELF_T_VDEF] = FALIGN(4,4),
#endif
#if LIBELF_CONFIG_VNEED
[ELF_T_VNEED] = FALIGN(4,4),
#endif
[ELF_T_WORD] = FALIGN(4,4),
[ELF_T_XWORD] = FALIGN(0,8),
[ELF_T_GNUHASH] = FALIGN(4,8)
#elif defined(_MSC_VER)
{ 4, 8 }, { 1, 1 }, { 4, 8 }, { 4, 8 }, { 4, 8 },
{ 2, 2 }, { 8, 8 }, { 8, 8 }, { 0, 0 }, { 4, 4 },
{ 4, 8 }, { 4, 8 }, { 4, 8 }, { 4, 8 }, { 4, 8 },
{ 4, 4 }, { 0, 8 }, { 4, 8 }, { 2, 2 }, { 4, 4 },
{ 4, 4 }, { 4, 4 }, { 0, 8 }, { 4, 8 }
#else
#error
#endif
};
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);
}
@@ -0,0 +1,228 @@
/*-
* 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 <sys/cdefs.h>
#if !defined(WIN32)
#include <sys/errno.h>
#endif
#include <assert.h>
#include <errno.h>
#include <libelf.h>
#include <stdlib.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_allocate.c 1341 2011-01-01 04:28:29Z jkoshy $");
Elf *
_libelf_allocate_elf(Elf_Mem *mem)
{
Elf *e;
if (mem != NULL) {
if ((e = mem->alloc(sizeof(*e))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
return NULL;
}
e->e_mem.dealloc = mem->dealloc;
e->e_mem.alloc = mem->alloc;
} else {
if ((e = malloc(sizeof(*e))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
return NULL;
}
e->e_mem.dealloc = &free;
e->e_mem.alloc = &malloc;
}
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(E, P) do { \
if (P) \
E->e_mem.dealloc(P); \
} while (0)
Elf *
_libelf_release_elf(Elf *e)
{
Elf_Arhdr *arh;
switch (e->e_kind) {
case ELF_K_AR:
FREE(e, e->e_u.e_ar.e_symtab);
break;
case ELF_K_ELF:
switch (e->e_class) {
case ELFCLASS32:
FREE(e, e->e_u.e_elf.e_ehdr.e_ehdr32);
FREE(e, e->e_u.e_elf.e_phdr.e_phdr32);
break;
case ELFCLASS64:
FREE(e, e->e_u.e_elf.e_ehdr.e_ehdr64);
FREE(e, 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(e, arh->ar_name);
FREE(e, arh->ar_rawname);
e->e_mem.dealloc(arh);
}
break;
default:
break;
}
e->e_mem.dealloc(e);
return (NULL);
}
Elf_Data *
_libelf_allocate_data(Elf_Scn *s)
{
Elf_Data *d;
if ((d = s->s_elf->e_mem.alloc(sizeof(Elf_Data))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
memset(d, 0, sizeof(*d));
d->d_scn = s;
return (d);
}
Elf_Data *
_libelf_release_data(Elf_Data *d)
{
if (d->d_flags & LIBELF_F_DATA_MALLOCED)
d->d_scn->s_elf->e_mem.dealloc(d->d_buf);
d->d_scn->s_elf->e_mem.dealloc(d);
return (NULL);
}
Elf_Scn *
_libelf_allocate_scn(Elf *e, size_t ndx)
{
Elf_Scn *s;
if ((s = e->e_mem.alloc(sizeof(Elf_Scn))) == NULL) {
LIBELF_SET_ERROR(RESOURCE, errno);
return (NULL);
}
memset(s, 0, sizeof(*s));
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;
Elf_Data *d, *td;
assert(s != NULL);
STAILQ_FOREACH_SAFE(d, &s->s_data, d_next, td) {
STAILQ_REMOVE(&s->s_data, d, _Elf_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, _Elf_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);
e->e_mem.dealloc(s);
return (NULL);
}
@@ -0,0 +1,458 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <ctype.h>
#include <libelf.h>
#include <stdlib.h>
#include <string.h>
#include "_libelf.h"
#include "_libelf_ar.h"
LIBELF_VCSID("$Id: libelf_ar.c 1341 2011-01-01 04:28:29Z jkoshy $");
#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 <ar.h> (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;
char *namelen;
Elf_Arhdr *eh;
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 = e->e_mem.alloc(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)
e->e_mem.dealloc(eh->ar_name);
if (eh->ar_rawname)
e->e_mem.dealloc(eh->ar_rawname);
e->e_mem.dealloc(eh);
}
e->e_flags &= ~LIBELF_F_AR_HEADER;
e->e_hdr.e_rawhdr = (char *) arh;
return (NULL);
}
Elf *
_libelf_ar_open_member(int fd, Elf_Cmd c, Elf *elf, Elf_Mem* mem)
{
Elf *e;
char *member, *namelen;
size_t nsz, sz;
off_t next;
struct ar_hdr *arh;
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((char *) member, sz, mem)) == NULL)
return (NULL);
e->e_fd = fd;
e->e_cmd = c;
e->e_hdr.e_rawhdr = (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 char *end, *p, *p0, *s, *s0;
const unsigned int entrysize = 2 * sizeof(long);
long arraysize, fileoffset, n, nentries, 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 (p0 + arraysize >= end || (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 (s0 + strtabsize > end)
goto symtaberror;
nentries = arraysize / entrysize;
/*
* Allocate space for the returned Elf_Arsym array.
*/
if ((symtab = e->e_mem.alloc(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);
s = s0 + stroffset;
if (s >= end)
goto symtaberror;
sym->as_off = 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)
e->e_mem.dealloc(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)
{
size_t n, nentries, off;
Elf_Arsym *symtab, *sym;
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 = 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 = e->e_mem.alloc(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;
off = 0;
GET_WORD(p, off);
sym->as_off = 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)
e->e_mem.dealloc(symtab);
LIBELF_SET_ERROR(ARCHIVE, 0);
return (NULL);
}
@@ -0,0 +1,354 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <libelf.h>
#include <stdlib.h>
#include <string.h>
#include "_libelf.h"
#include "_libelf_ar.h"
LIBELF_VCSID("$Id: libelf_ar_util.c 2066 2011-10-26 15:40:28Z jkoshy $");
/*
* Convert a string bounded by `start' and `start+sz' (exclusive) to a
* number in the specified base.
*/
int
_libelf_ar_get_number(const char *s, size_t sz, int base, size_t *ret)
{
int c, v;
size_t r;
const char *e;
assert(base <= 10);
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 c, *s;
size_t len, offset;
const 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 char *) arh >= ar->e_rawfile &&
(const char *) arh < ar->e_rawfile + ar->e_rawsize);
buf = 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(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 = p - q + 1; /* space for the trailing NUL */
if ((s = ar->e_mem.alloc(len)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
(void) strncpy(s, 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(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 = ar->e_mem.alloc(len + 1)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
/*
* The file name follows the archive header.
*/
q = (const char *) (arh + 1);
(void) strncpy(s, 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 = q - buf + 2; /* Add space for a trailing NUL. */
} else {
/* The buffer only had blanks. */
buf = "";
len = 1;
}
if ((s = ar->e_mem.alloc(len)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
(void) strncpy(s, 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 scanahead;
char *s, *end;
size_t sz;
struct ar_hdr arh;
e->e_kind = 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((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] == '/') {
assert(sz > 0);
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:
LIBELF_SET_ERROR(ARCHIVE, 0);
return (NULL);
}
@@ -0,0 +1,100 @@
/*-
* 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 <sys/cdefs.h>
#include <gelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_checksum.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
unsigned 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, d->d_size);
}
/*
* Return a 16-bit checksum compatible with Solaris.
*/
return (((checksum >> 16) & 0xFFFFUL) + (checksum & 0xFFFFUL));
}
@@ -0,0 +1,114 @@
/*-
* 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 <sys/cdefs.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_data.c 1264 2010-11-12 14:53:23Z jkoshy $");
int
_libelf_xlate_shtype(uint32_t sht)
{
switch (sht) {
case SHT_DYNAMIC:
return (ELF_T_DYN);
case SHT_DYNSYM:
return (ELF_T_SYM);
#if defined(SHT_FINI_ARRAY)
case SHT_FINI_ARRAY:
return (ELF_T_ADDR);
#endif
#if defined(SHT_GNU_HASH)
case SHT_GNU_HASH:
return (ELF_T_GNUHASH);
#endif
#if defined(SHT_GNU_LIBLIST)
case SHT_GNU_LIBLIST:
return (ELF_T_WORD);
#endif
#if defined(SHT_GROUP)
case SHT_GROUP:
return (ELF_T_WORD);
#endif
case SHT_HASH:
return (ELF_T_WORD);
#if defined(SHT_INIT_ARRAY)
case SHT_INIT_ARRAY:
return (ELF_T_ADDR);
#endif
case SHT_NOBITS:
return (ELF_T_BYTE);
case SHT_NOTE:
return (ELF_T_NOTE);
#if defined(SHT_PREINIT_ARRAY)
case SHT_PREINIT_ARRAY:
return (ELF_T_ADDR);
#endif
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);
#if defined(SHT_SYMTAB_SHNDX)
case SHT_SYMTAB_SHNDX:
return (ELF_T_WORD);
#endif
#if defined(SHT_SUNW_dof)
case SHT_SUNW_dof:
return (ELF_T_BYTE);
#endif
#if defined(SHT_SUNW_move)
case SHT_SUNW_move:
return (ELF_T_MOVE);
#endif
#if defined(SHT_SUNW_syminfo)
case SHT_SUNW_syminfo:
return (ELF_T_SYMINFO);
#endif
#if defined(SHT_SUNW_verdef)
case SHT_SUNW_verdef: /* == SHT_GNU_verdef */
return (ELF_T_VDEF);
#endif
#if defined(SHT_SUNW_verneed)
case SHT_SUNW_verneed: /* == SHT_GNU_verneed */
return (ELF_T_VNEED);
#endif
#if defined(SHT_SUNW_versym)
case SHT_SUNW_versym: /* == SHT_GNU_versym */
return (ELF_T_HALF);
#endif
default:
return (-1);
}
}
@@ -0,0 +1,211 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include <libelf.h>
#include <stdlib.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_ehdr.c 1677 2011-07-28 04:35:53Z jkoshy $");
/*
* 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)(char *_d, size_t _dsz, 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)((char *) &scn->s_shdr, sizeof(scn->s_shdr),
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 = 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); \
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)(char *_d, size_t _dsz, 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 we have a file that is attached to a read/write elf
// or the elf is a read only elf and the size is smaller than the
// file, then error.
if ((e->e_cmd == ELF_C_READ || (e->e_cmd == ELF_C_RDWR && e->e_rawfile)) && 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 = e->e_mem.alloc(msz)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
memset(ehdr, 0, msz);
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 there is no raw file, return as we are done and don't need to
// process the file on the disk.
if (!e->e_rawfile)
return (ehdr);
xlator = _libelf_get_translator(ELF_T_EHDR, ELF_TOMEMORY, ec);
(*xlator)(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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_extended.c 1360 2011-01-08 08:27:41Z jkoshy $");
/*
* 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;
else
((Elf64_Ehdr *) eh)->e_shnum = shnum;
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;
else
((Elf64_Ehdr *) eh)->e_shstrndx = shstrndx;
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;
else
((Elf64_Ehdr *) eh)->e_phnum = phnum;
return (1);
}
@@ -0,0 +1,147 @@
/*-
* 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 <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_fsize.m4 320 2009-03-07 16:37:53Z jkoshy $");
/* WARNING: GENERATED FROM libelf_fsize.m4. */
/*
* Create an array of file sizes from the elf_type definitions
*/
struct fsize {
size_t fsz32;
size_t fsz64;
};
static struct fsize fsize[ELF_T_NUM] = {
#if defined(__GNUC__)
#if LIBELF_CONFIG_ADDR
[ELF_T_ADDR] = { .fsz32 = sizeof(Elf32_Addr), .fsz64 = sizeof(Elf64_Addr) },
#endif
#if LIBELF_CONFIG_BYTE
[ELF_T_BYTE] = { .fsz32 = 1, .fsz64 = 1 },
#endif
#if LIBELF_CONFIG_CAP
[ELF_T_CAP] = { .fsz32 = sizeof(Elf32_Word)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_DYN
[ELF_T_DYN] = { .fsz32 = sizeof(Elf32_Sword)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Sxword)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_EHDR
[ELF_T_EHDR] = { .fsz32 = EI_NIDENT+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Word)+sizeof(Elf32_Addr)+sizeof(Elf32_Off)+sizeof(Elf32_Off)+sizeof(Elf32_Word)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+0, .fsz64 = EI_NIDENT+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Word)+sizeof(Elf64_Addr)+sizeof(Elf64_Off)+sizeof(Elf64_Off)+sizeof(Elf64_Word)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
#endif
#if LIBELF_CONFIG_GNUHASH
[ELF_T_GNUHASH] = { .fsz32 = 1, .fsz64 = 1 },
#endif
#if LIBELF_CONFIG_HALF
[ELF_T_HALF] = { .fsz32 = sizeof(Elf32_Half), .fsz64 = sizeof(Elf64_Half) },
#endif
#if LIBELF_CONFIG_LWORD
[ELF_T_LWORD] = { .fsz32 = sizeof(Elf32_Lword), .fsz64 = sizeof(Elf64_Lword) },
#endif
#if LIBELF_CONFIG_MOVE
[ELF_T_MOVE] = { .fsz32 = sizeof(Elf32_Lword)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+0, .fsz64 = sizeof(Elf64_Lword)+sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
#endif
#if LIBELF_CONFIG_MOVEP
[ELF_T_MOVEP] = { .fsz32 = 0, .fsz64 = 0 },
#endif
#if LIBELF_CONFIG_NOTE
[ELF_T_NOTE] = { .fsz32 = 1, .fsz64 = 1 },
#endif
#if LIBELF_CONFIG_OFF
[ELF_T_OFF] = { .fsz32 = sizeof(Elf32_Off), .fsz64 = sizeof(Elf64_Off) },
#endif
#if LIBELF_CONFIG_PHDR
[ELF_T_PHDR] = { .fsz32 = sizeof(Elf32_Word)+sizeof(Elf32_Off)+sizeof(Elf32_Addr)+sizeof(Elf32_Addr)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)+sizeof(Elf64_Off)+sizeof(Elf64_Addr)+sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_REL
[ELF_T_REL] = { .fsz32 = sizeof(Elf32_Addr)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_RELA
[ELF_T_RELA] = { .fsz32 = sizeof(Elf32_Addr)+sizeof(Elf32_Word)+sizeof(Elf32_Sword)+0, .fsz64 = sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+sizeof(Elf64_Sxword)+0 },
#endif
#if LIBELF_CONFIG_SHDR
[ELF_T_SHDR] = { .fsz32 = sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Addr)+sizeof(Elf32_Off)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Word)+sizeof(Elf64_Word)+sizeof(Elf64_Xword)+sizeof(Elf64_Addr)+sizeof(Elf64_Off)+sizeof(Elf64_Xword)+sizeof(Elf64_Word)+sizeof(Elf64_Word)+sizeof(Elf64_Xword)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_SWORD
[ELF_T_SWORD] = { .fsz32 = sizeof(Elf32_Sword), .fsz64 = sizeof(Elf64_Sword) },
#endif
#if LIBELF_CONFIG_SXWORD
[ELF_T_SXWORD] = { .fsz32 = 0, .fsz64 = sizeof(Elf64_Sxword) },
#endif
#if LIBELF_CONFIG_SYMINFO
[ELF_T_SYMINFO] = { .fsz32 = sizeof(Elf32_Half)+sizeof(Elf32_Half)+0, .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+0 },
#endif
#if LIBELF_CONFIG_SYM
[ELF_T_SYM] = { .fsz32 = sizeof(Elf32_Word)+sizeof(Elf32_Addr)+sizeof(Elf32_Word)+1+1+sizeof(Elf32_Half)+0, .fsz64 = sizeof(Elf64_Word)+1+1+sizeof(Elf64_Half)+sizeof(Elf64_Addr)+sizeof(Elf64_Xword)+0 },
#endif
#if LIBELF_CONFIG_VDEF
[ELF_T_VDEF] = { .fsz32 = sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Word)+sizeof(Elf64_Word)+sizeof(Elf64_Word)+0 },
#endif
#if LIBELF_CONFIG_VNEED
[ELF_T_VNEED] = { .fsz32 = sizeof(Elf32_Half)+sizeof(Elf32_Half)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+sizeof(Elf32_Word)+0, .fsz64 = sizeof(Elf64_Half)+sizeof(Elf64_Half)+sizeof(Elf64_Word)+sizeof(Elf64_Word)+sizeof(Elf64_Word)+0 },
#endif
#if LIBELF_CONFIG_WORD
[ELF_T_WORD] = { .fsz32 = sizeof(Elf32_Word), .fsz64 = sizeof(Elf64_Word) },
#endif
#if LIBELF_CONFIG_XWORD
[ELF_T_XWORD] = { .fsz32 = 0, .fsz64 = sizeof(Elf64_Xword) },
#endif
#elif defined(_MSC_VER)
{4, 8}, {1, 1}, {0, 0}, {8, 16}, {52, 64},
{2, 2}, {0, 0}, {0, 0}, {0, 0}, {1, 1},
{4, 8}, {32, 56}, {8, 16}, {12, 24}, {40, 64},
{4, 4}, {0, 8}, {0, 0}, {16, 24}, {20, 20},
{16, 16}, {4, 4}, {0, 8}, {1, 1}
#else
#error
#endif
};
size_t
_libelf_fsize(Elf_Type t, int ec, unsigned int v, size_t c)
{
size_t sz;
sz = 0;
if (v != EV_CURRENT)
LIBELF_SET_ERROR(VERSION, 0);
else if ((int) t < ELF_T_FIRST || t > ELF_T_LAST)
LIBELF_SET_ERROR(ARGUMENT, 0);
else {
sz = ec == ELFCLASS64 ? fsize[t].fsz64 : fsize[t].fsz32;
if (sz == 0)
LIBELF_SET_ERROR(UNIMPL, 0);
}
return (sz*c);
}
@@ -0,0 +1,145 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <libelf.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_msize.m4 311 2009-02-26 16:46:31Z jkoshy $");
/* WARNING: GENERATED FROM libelf_msize.m4. */
struct msize {
size_t msz32;
size_t msz64;
};
static struct msize msize[ELF_T_NUM] = {
#if defined(__GNUC__)
#if LIBELF_CONFIG_ADDR
[ELF_T_ADDR] = { .msz32 = sizeof(Elf32_Addr), .msz64 = sizeof(Elf64_Addr) },
#endif
#if LIBELF_CONFIG_BYTE
[ELF_T_BYTE] = { .msz32 = 1, .msz64 = 1 },
#endif
#if LIBELF_CONFIG_CAP
[ELF_T_CAP] = { .msz32 = sizeof(Elf32_Cap), .msz64 = sizeof(Elf64_Cap) },
#endif
#if LIBELF_CONFIG_DYN
[ELF_T_DYN] = { .msz32 = sizeof(Elf32_Dyn), .msz64 = sizeof(Elf64_Dyn) },
#endif
#if LIBELF_CONFIG_EHDR
[ELF_T_EHDR] = { .msz32 = sizeof(Elf32_Ehdr), .msz64 = sizeof(Elf64_Ehdr) },
#endif
#if LIBELF_CONFIG_GNUHASH
[ELF_T_GNUHASH] = { .msz32 = 1, .msz64 = 1 },
#endif
#if LIBELF_CONFIG_HALF
[ELF_T_HALF] = { .msz32 = sizeof(Elf32_Half), .msz64 = sizeof(Elf64_Half) },
#endif
#if LIBELF_CONFIG_LWORD
[ELF_T_LWORD] = { .msz32 = sizeof(Elf32_Lword), .msz64 = sizeof(Elf64_Lword) },
#endif
#if LIBELF_CONFIG_MOVE
[ELF_T_MOVE] = { .msz32 = sizeof(Elf32_Move), .msz64 = sizeof(Elf64_Move) },
#endif
#if LIBELF_CONFIG_MOVEP
[ELF_T_MOVEP] = { .msz32 = 0, .msz64 = 0 },
#endif
#if LIBELF_CONFIG_NOTE
[ELF_T_NOTE] = { .msz32 = 1, .msz64 = 1 },
#endif
#if LIBELF_CONFIG_OFF
[ELF_T_OFF] = { .msz32 = sizeof(Elf32_Off), .msz64 = sizeof(Elf64_Off) },
#endif
#if LIBELF_CONFIG_PHDR
[ELF_T_PHDR] = { .msz32 = sizeof(Elf32_Phdr), .msz64 = sizeof(Elf64_Phdr) },
#endif
#if LIBELF_CONFIG_REL
[ELF_T_REL] = { .msz32 = sizeof(Elf32_Rel), .msz64 = sizeof(Elf64_Rel) },
#endif
#if LIBELF_CONFIG_RELA
[ELF_T_RELA] = { .msz32 = sizeof(Elf32_Rela), .msz64 = sizeof(Elf64_Rela) },
#endif
#if LIBELF_CONFIG_SHDR
[ELF_T_SHDR] = { .msz32 = sizeof(Elf32_Shdr), .msz64 = sizeof(Elf64_Shdr) },
#endif
#if LIBELF_CONFIG_SWORD
[ELF_T_SWORD] = { .msz32 = sizeof(Elf32_Sword), .msz64 = sizeof(Elf64_Sword) },
#endif
#if LIBELF_CONFIG_SXWORD
[ELF_T_SXWORD] = { .msz32 = 0, .msz64 = sizeof(Elf64_Sxword) },
#endif
#if LIBELF_CONFIG_SYMINFO
[ELF_T_SYMINFO] = { .msz32 = sizeof(Elf32_Syminfo), .msz64 = sizeof(Elf64_Syminfo) },
#endif
#if LIBELF_CONFIG_SYM
[ELF_T_SYM] = { .msz32 = sizeof(Elf32_Sym), .msz64 = sizeof(Elf64_Sym) },
#endif
#if LIBELF_CONFIG_VDEF
[ELF_T_VDEF] = { .msz32 = sizeof(Elf32_Verdef), .msz64 = sizeof(Elf64_Verdef) },
#endif
#if LIBELF_CONFIG_VNEED
[ELF_T_VNEED] = { .msz32 = sizeof(Elf32_Verneed), .msz64 = sizeof(Elf64_Verneed) },
#endif
#if LIBELF_CONFIG_WORD
[ELF_T_WORD] = { .msz32 = sizeof(Elf32_Word), .msz64 = sizeof(Elf64_Word) },
#endif
#if LIBELF_CONFIG_XWORD
[ELF_T_XWORD] = { .msz32 = 0, .msz64 = sizeof(Elf64_Xword) },
#endif
#elif defined(_MSC_VER)
{4, 8}, {1, 1}, {0, 0}, {8, 16}, {52, 64},
{2, 2}, {0, 0}, {0, 0}, {0, 0}, {1, 1},
{4, 8}, {32, 56}, {8, 16}, {12, 24}, {40, 64},
{4, 4}, {0, 8}, {0, 0}, {16, 24}, {20, 20},
{16, 16}, {4, 4}, {0, 8}, {1, 1}
#else
#error
#endif
};
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);
}
@@ -0,0 +1,160 @@
/*-
* 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 <sys/cdefs.h>
#include <assert.h>
#include <gelf.h>
#include <libelf.h>
#include <stdlib.h>
#include <string.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_phdr.c 1677 2011-07-28 04:35:53Z jkoshy $");
void *
_libelf_getphdr(Elf *e, int ec)
{
size_t phnum, phentsize;
size_t fsz, msz;
uint64_t phoff;
Elf32_Ehdr *eh32;
Elf64_Ehdr *eh64;
void *ehdr, *phdr;
int (*xlator)(char *_d, size_t _dsz, 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;
phentsize = eh32->e_phentsize;
phoff = (uint64_t) eh32->e_phoff;
} else {
eh64 = (Elf64_Ehdr *) ehdr;
phentsize = eh64->e_phentsize;
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 = e->e_mem.alloc(phnum * msz)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
memset(phdr, 0, msz);
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 = e->e_mem.alloc(count * msz)) == NULL) {
LIBELF_SET_ERROR(RESOURCE, 0);
return (NULL);
}
if (count > 0) {
memset(newphdr, 0, count * msz);
}
if (ec == ELFCLASS32) {
if ((oldphdr = (void *) e->e_u.e_elf.e_phdr.e_phdr32) != NULL)
e->e_mem.dealloc(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)
e->e_mem.dealloc(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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <gelf.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_shdr.c 189 2008-07-20 10:38:08Z jkoshy $");
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);
}
@@ -0,0 +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 <sys/cdefs.h>
#include <assert.h>
#include <libelf.h>
#include "_libelf.h"
LIBELF_VCSID("$Id: libelf_xlate.c 316 2009-02-28 16:08:44Z jkoshy $");
/*
* 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 = src->d_size / fsz;
dsz = cnt * msz;
} else {
cnt = 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 + src->d_size;
db = (uintptr_t) dst->d_buf;
de = db + 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);
}
@@ -0,0 +1,403 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
//
// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
//
#include "memfile.h"
#include <errno.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <algorithm>
#include <vector>
#include <cstring>
#if defined(__GNUC__)
#include <unistd.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#else
#include <io.h>
#if !defined(PROT_READ)
#define PROT_READ 0x0004 // FILE_MAP_READ
#endif
#if !defined(MAP_PRIVATE)
#define MAP_PRIVATE 0x0001 // FILE_MAP_COPY
#endif
#endif
// Allocation granularity
#define ALLOC_G 512
#define is_file(fd) ((fd) >= 0)
#if defined(_WIN32)
#define OPEN ::_open
#define READ(f, b, l) ::_read((f), (b), (unsigned int)(l))
#define WRITE(f, b, l) ::_write((f), (b), (unsigned int)(l))
#define CLOSE ::_close
#define LSEEK ::_lseek
#define FSTAT ::fstat
#define FTRUNC(f, l) ::_chsize((f), (long)(l))
#define MMAP ::w32_mmap
#define MUNMAP ::w32_munmap
#else
#define OPEN ::open
#define READ(f, b, l) ::read((f), (b), (size_t)(l))
#define WRITE ::write
#define CLOSE ::close
#define LSEEK ::lseek
#define FSTAT ::fstat
#define FTRUNC(f, l) ::ftruncate((f), (off_t)(l))
#define MMAP ::mmap
#define MUNMAP ::munmap
#endif
#if defined(_WIN32)
extern "C" void* w32_mmap(void* start, size_t length, int prot, int flags, int fd, unsigned offset);
extern "C" int w32_munmap(void* start, size_t length);
#endif
namespace amd {
// A structure which either maintains in memory file or uses a real file.
class memfile_t {
public:
memfile_t() : buf(nullptr), curp(nullptr), size(0) {}
bool reserve(size_t new_size) {
if (!new_size)
new_size = 1;
new_size = (new_size + ALLOC_G - 1) & ~(ALLOC_G - 1);
size_t pos = tell();
void *p = realloc(buf, new_size);
if (!p)
return false;
buf = p;
setpos(pos);
return true;
}
bool open(int oflag, int pmode)
{
size = 0;
buf = curp = nullptr;
return reserve(1);
}
off_t read(void *buffer, size_t count)
{
if (!buffer) {
errno = EINVAL;
return -1;
}
size_t pos = tell();
if (pos >= size)
return 0;
size_t ret = size - pos;
ret = std::min(ret, count);
memcpy(buffer, curp, ret);
advance(ret);
return (off_t)ret;
}
off_t write(const void *buffer, size_t count)
{
if (!buffer) {
errno = EINVAL;
return -1;
}
size_t pos = tell();
size_t new_size = std::max(pos + count, size);
if (new_size > size) {
if (!reserve(new_size))
return -1;
if (pos > size)
memset((char*)buf + size, 0, pos - size);
size = new_size;
}
memcpy(curp, buffer, count);
advance(count);
return (off_t)count;
}
int close() {
if (is_open()) {
free(buf);
buf = nullptr;
size = 0;
return 0;
}
errno = EBADF;
return -1;
}
off_t lseek(off_t offset, int origin)
{
switch (origin) {
default:
errno = EINVAL;
return -1;
case SEEK_SET:
break;
case SEEK_CUR:
offset += (off_t)tell();
break;
case SEEK_END:
offset += (off_t)size;
break;
}
if (offset < 0) {
errno = EOVERFLOW;
return -1;
}
setpos((size_t)offset);
return offset;
}
bool fstat(struct stat *buf) const
{
if (!is_open()) {
errno = EBADF;
return false;
}
memset(buf, 0, sizeof(struct stat));
buf->st_mode = S_IFREG;
buf->st_size = (off_t)size;
return true;
}
bool ftruncate(size_t len)
{
if (len > size) {
size_t pos = tell();
lseek(0, SEEK_END);
while(len--)
write("", 1u);
setpos(len);
} else {
reserve(len);
size = len;
}
return true;
}
bool is_open() const { return buf != nullptr; }
size_t tell() const { return size_t((char*)curp - (char*)buf); }
void* get() const { return buf; }
protected:
void setpos(size_t new_pos) { curp = (char*)buf + new_pos; }
void advance(off_t offset) { curp = (char*)curp + offset; }
void advance(size_t offset) { curp = (char*)curp + offset; }
private:
void* buf;
void* curp;
size_t size;
};
} // namespace amd
using namespace amd;
static std::vector<memfile_t> Files;
static size_t fd2idx(int fd)
{
return (unsigned)-fd - 2;
}
static int idx2fd(size_t idx)
{
return -(int)idx - 2;
}
static memfile_t* get_memfile(int fd)
{
if (fd >= -1) {
errno = EBADF;
return nullptr;
}
size_t fno = fd2idx(fd);
if (fno >= Files.size()) {
errno = EBADF;
return nullptr;
}
memfile_t &m = Files[fno];
if (!m.is_open()) {
errno = EBADF;
return nullptr;
}
return &m;
}
// Acts the same as open(), but path can be NULL, which is a request for in memory file
int mem_open(const char *path, int oflag, int pmode)
{
if (path && path[0]) // Filename provided, real file requested
return OPEN(path, oflag, pmode);
memfile_t m;
if (!m.open(oflag, pmode))
return -1;
for (size_t i = 0; i < Files.size(); ++i) {
if (!Files[i].is_open()) {
Files[i] = m;
return idx2fd(i);
}
}
Files.push_back(m);
return idx2fd(Files.size() - 1);
}
off_t mem_read(int fd, void *buffer, size_t count)
{
if (is_file(fd))
return READ(fd, buffer, count);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
return m->read(buffer, count);
}
off_t mem_write(int fd, const void *buffer, size_t count)
{
if (is_file(fd))
return WRITE(fd, buffer, count);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
return m->write(buffer, count);
}
int mem_close(int fd)
{
if (is_file(fd))
return CLOSE(fd);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
int ret = m->close();
if ((size_t)fd == (Files.size() - 1))
Files.pop_back();
return ret;
}
off_t mem_lseek(int fd, off_t offset, int origin)
{
if (is_file(fd))
return LSEEK(fd, offset, origin);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
return m->lseek(offset, origin);
}
int mem_fstat(int fd, struct stat *buf)
{
if (is_file(fd))
return FSTAT(fd, buf);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
return m->fstat(buf) ? 0 : -1;
}
int mem_ftruncate(int fd, size_t len)
{
if (is_file(fd))
return FTRUNC(fd, len);
memfile_t *m = get_memfile(fd);
if (!m)
return -1;
return m->ftruncate(len) ? 0 : -1;
}
off_t mem_sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
{
#if defined(__GNUC__)
if (is_file(in_fd) && is_file(out_fd))
return sendfile(out_fd, in_fd, offset, count);
#endif
off_t start = offset ? *offset : mem_lseek(in_fd, 0, SEEK_CUR);
struct stat sb;
if (mem_fstat(in_fd, &sb) == -1)
return -1;
if (start < 0 || sb.st_size <= start)
return 0;
count = std::min(count, (size_t)(sb.st_size - start));
void *in = mem_mmap(NULL, count, PROT_READ, MAP_PRIVATE, in_fd, start);
if ((void*)-1 == in)
return -1;
off_t written = mem_write(out_fd, in, count);
mem_munmap(in, count);
if (written < 0)
return -1;
if (offset) {
*offset += written;
} else {
if (mem_lseek(in_fd, written, SEEK_CUR) < 0)
return -1;
}
return written;
}
void* mem_mmap(void* start, size_t length, int prot, int flags, int fd, unsigned offset)
{
if (is_file(fd))
return MMAP(start, length, prot, flags, fd, offset);
memfile_t *m = get_memfile(fd);
if (!m)
return (void*)-1;
return (char*)m->get() + offset;
}
int mem_munmap(void* start, size_t length)
{
MUNMAP(start, length);
return 0;
}
@@ -0,0 +1,40 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
//
// Copyright (c) 2016 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _MEMFILE_H
#define _MEMFILE_H
#include <sys/types.h>
#if !defined(_MSC_VER)
#include <sys/stat.h>
#endif
#if defined(__cplusplus)
extern "C" {
#endif
// Acts the same as open(), but path can be NULL, which is a request for in memory file
extern int mem_open(const char *path, int oflag, int pmode);
extern off_t mem_read(int fd, void *buffer, size_t count);
extern off_t mem_write(int fd, const void *buffer, size_t count);
extern int mem_close(int fd);
extern off_t mem_lseek(int fd, off_t offset, int origin);
extern int mem_fstat(int fd, struct stat *buf);
extern int mem_ftruncate(int fd, size_t len);
extern off_t mem_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
extern void* mem_mmap(void* start, size_t length, int prot, int flags, int fd, unsigned offset);
extern int mem_munmap(void* start, size_t length);
#if defined(__cplusplus)
}
#endif
#endif // !_MEMFILE_H
@@ -0,0 +1,15 @@
/*
************************************************************************************************************************
*
* Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
***********************************************************************************************************************/
#ifdef __GNUC__
# define roundup(x, y) (__builtin_constant_p (y) && powerof2 (y) \
? (((x) + (y) - 1) & ~((y) - 1)) \
: ((((x) + ((y) - 1)) / (y)) * (y)))
#else
# define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
#endif