initial commit

[ROCm/clr commit: 3694ab2ce8]
This commit is contained in:
foreman
2014-07-04 16:17:05 -04:00
vanhempi b0b5b33fcf
commit f80f2f233c
351 muutettua tiedostoa jossa 113713 lisäystä ja 1 poistoa
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,99 @@
EXPORTS
aclLoader_OnLoad
aclLoader_OnUnload
aclCompilerInit
aclCompilerFini
aclCompilerVersion
aclVersionSize
aclGetErrorString
aclGetArchInfo
aclGetDeviceInfo
aclGetTargetInfo
aclGetArchitecture
aclGetFamily
aclGetChip
aclBinaryInit
aclBinaryFini
aclReadFromFile
aclReadFromMem
aclWriteToFile
aclWriteToMem
aclCreateFromBinary
aclBinaryVersion
aclInsertSection
aclRemoveSection
aclExtractSection
aclInsertSymbol
aclRemoveSymbol
aclExtractSymbol
aclDbgAddArgument
aclDbgRemoveArgument
aclQueryInfo
aclCompile
aclLink
aclGetCompilerLog
aclRetrieveType
aclSetType
aclConvertType
aclDisassemble
aclGetDeviceBinary
oclCompilerInit
oclCompilerFini
oclCompilerVersion
oclVersionSize
oclCompileSource
oclCompileSourceToIR
oclCompileIRToIL
oclCompileILToISA
oclCompileBinary
oclGetCompilerLog
oclGetArchInfo
oclGetFamilyInfo
oclGetDeviceInfo
oclGetAsicInfo
oclGetTargetInfo
oclGetArchitecture
oclGetFamily
oclGetChip
oclGetAsic
elfInsertSection
elfExtractSection
elfInsertSymbol
elfExtractSymbol
oclirSetType
oclirRetrieveType
oclirLink
oclhsaCompileSource
oclhsaCompileBinary
oclhsaSetType
oclhsaRetrieveType
oclhsaConvertType
oclilCompileSource
oclilCompileBinary
oclilSetType
oclilRetrieveType
oclilConvertType
oclisaDisassemble
oclisaGetBinaryBlob
constructOclElf
destructOclElf
readOclElfFromFile
readOclElfFromMem
writeOclElfToFile
writeOclElfToMem
createElfFromElf
getBIFVersion
rtGetInfo
aclDumpBinary
aclJITObjectImageCreate
aclJITObjectImageCopy
aclJITObjectImageDestroy
aclJITObjectImageFinalize
aclJITObjectImageSize
aclJITObjectImageData
aclJITObjectImageDisassembleKernel
aclJITObjectImageIterateSymbols
aclJITObjectImageGetGlobalsSize
#if defined(WITH_TARGET_HSAIL)
aclHsaLoader
#endif
@@ -0,0 +1,104 @@
ACL_API_0.8 {
global:
oclCompilerInit;
oclCompilerFini;
oclCompilerVersion;
oclVersionSize;
oclCompileSource;
oclCompileSourceToIR;
oclCompileIRToIL;
oclCompileILToISA;
oclCompileBinary;
oclGetCompilerLog;
oclGetArchInfo;
oclGetDeviceInfo;
oclGetTargetInfo;
oclGetArchitecture;
oclGetFamily;
oclGetChip;
readOclElfFromFile;
readOclElfFromMem;
writeOclElfToFile;
writeOclElfToMem;
createElfFromElf;
getBIFVersion;
constructOclElf;
destructOclElf;
elfInsertSection;
elfExtractSection;
elfInsertSymbol;
elfExtractSymbol;
oclirSetType;
oclirRetrieveType;
oclirLink;
oclhsaCompileSource;
oclhsaCompileBinary;
oclhsaSetType;
oclhsaRetrieveType;
oclhsaConvertType;
oclilCompileSource;
oclilCompileBinary;
oclilSetType;
oclilRetrieveType;
oclilConvertType;
oclisaDisassemble;
oclisaGetBinaryBlob;
rtGetInfo;
aclCompilerInit;
aclCompilerFini;
aclCompilerVersion;
aclVersionSize;
aclGetErrorString;
aclGetArchInfo;
aclGetFamilyInfo;
aclGetDeviceInfo;
aclGetAsicInfo;
aclGetTargetInfo;
aclGetArchitecture;
aclGetFamily;
aclGetChip;
aclGetAsic;
aclBinaryInit;
aclBinaryFini;
aclReadFromFile;
aclReadFromMem;
aclWriteToFile;
aclWriteToMem;
aclCreateFromBinary;
aclBinaryVersion;
aclInsertSection;
aclRemoveSection;
aclExtractSection;
aclInsertSymbol;
aclRemoveSymbol;
aclExtractSymbol;
aclQueryInfo;
aclDbgAddArgument;
aclDbgRemoveArgument;
aclCompile;
aclLink;
aclGetCompilerLog;
aclRetrieveType;
aclSetType;
aclConvertType;
aclDisassemble;
aclGetDeviceBinary;
aclLoader_OnLoad;
aclLoader_OnUnload;
aclJITObjectImageCreate;
aclJITObjectImageCopy;
aclJITObjectImageDestroy;
aclJITObjectImageFinalize;
aclJITObjectImageSize;
aclJITObjectImageData;
aclJITObjectImageDisassembleKernel;
aclJITObjectImageIterateSymbols;
aclJITObjectImageGetGlobalsSize;
#if defined(WITH_TARGET_HSAIL)
aclHsaLoader;
#endif
#if defined(OPENCL_MAINLINE)
local:
*;
#endif
};
@@ -0,0 +1,75 @@
#define STR(__macro__) #__macro__
#define XSTR(__macro__) STR(__macro__)
#if defined(_DEBUG)
#define DEBUG_ONLY(x) x
#else
#define DEBUG_ONLY(x)
#endif
#define VERSION_PREFIX_MAJOR 1
#define VERSION_PREFIX_MINOR 1
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winresrc.h"
#include "utils/versions.hpp"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION AMD_COMPILER_MAJOR_VERSION,AMD_COMPILER_MINOR_VERSION,AMD_COMPILER_BUILD_NUMBER,AMD_COMPILER_REVISION_NUMBER
PRODUCTVERSION AMD_COMPILER_MAJOR_VERSION,AMD_COMPILER_MINOR_VERSION,AMD_COMPILER_BUILD_NUMBER,AMD_COMPILER_REVISION_NUMBER
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", " \0"
VALUE "CompanyName", "Advanced Micro Devices Inc.\0"
VALUE "FileDescription", AMD_COMPILER_NAME " OpenCL " XSTR(VERSION_PREFIX_MAJOR) "." XSTR(VERSION_PREFIX_MINOR) " Compiler\0"
VALUE "FileVersion", XSTR(AMD_COMPILER_MAJOR_VERSION) ", " XSTR(AMD_COMPILER_MINOR_VERSION) ", " XSTR(AMD_COMPILER_BUILD_NUMBER) ", " XSTR(AMD_COMPILER_REVISION_NUMBER) ", " XSTR(AMD_SC_COMPILER_REVISION_NUMBER)
VALUE "InternalName", "AOC"
VALUE "LegalCopyright", "Copyright (C) 2011 Advanced Micro Devices Inc.\0"
VALUE "OriginalFilename", "amdoclcl.dll"
VALUE "ProductName", "AMD Compiler Library " XSTR(VERSION_PREFIX_MAJOR) "." XSTR(VERSION_PREFIX_MINOR) " " AMD_COMPILER_INFO "\0"
VALUE "ProductVersion", XSTR(AMD_COMPILER_MAJOR_VERSION) ", " XSTR(AMD_COMPILER_MINOR_VERSION) ", " XSTR(AMD_COMPILER_BUILD_NUMBER) ", " XSTR(AMD_COMPILER_REVISION_NUMBER) ", " XSTR(AMD_SC_COMPILER_REVISION_NUMBER)
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
@@ -0,0 +1,33 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_BACKEND_HPP_
#define _BE_BACKEND_HPP_
#include "compiler_stage.hpp"
namespace amdcl
{
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::Backend
*
* @{
*/
class Backend : public CompilerStage {
Backend(Backend&); // DO NOT IMPLEMENT.
Backend(); // DO NOT IMPLEMENT.
public:
Backend(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: CompilerStage(cl, elf, log) {}
virtual ~Backend() {}
/*! Function that takes in a string that is a source file
* and generates the backend binary that is then
* inserted into the elf file at the correct location.
*/
virtual int jit(const std::string &source) = 0;
}; // class Backend
/*@}*/
}; // amdcl namespace
#endif // _BE_BACKEND_HPP
@@ -0,0 +1,367 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "codegen.hpp"
#include "utils/libUtils.h"
#include "os/os.hpp"
#include "jit/src/jit.hpp"
#include "utils/target_mappings.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/DataLayout.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/CommandLine.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <memory>
using namespace amdcl;
using namespace llvm;
#ifdef WITH_TARGET_HSAIL
// Variable FileType are checked by HSAILTargetMachine, but only
// created in llc.exe. Create it here for online compilation path.
llvm::cl::opt<TargetMachine::CodeGenFileType>
FileType("filetype", cl::init(TargetMachine::CGFT_ObjectFile),
cl::values(
clEnumValN(TargetMachine::CGFT_AssemblyFile, "asm", ""),
clEnumValN(TargetMachine::CGFT_ObjectFile, "obj", ""),
clEnumValN(TargetMachine::CGFT_Null, "null", ""),
clEnumValEnd));
#endif
static std::string aclGetCodegenName(const aclTargetInfo &tgtInfo)
{
assert(tgtInfo.arch_id <= aclLast && "Unknown device id!");
const FamilyMapping *family = familySet + tgtInfo.arch_id;
if (!family) return "";
assert((tgtInfo.chip_id) < family->children_size && "Unknown family id!");
const TargetMapping *target = &family->target[tgtInfo.chip_id];
return (target) ? target->codegen_name : "";
}
/*! Function that modifies the code gen level based on the
* function size threshhold.
*/
static CodeGenOpt::Level
AdjustCGOptLevel(Module& M, CodeGenOpt::Level OrigOLvl)
{
const unsigned int FuncSizeThreshold = 10000;
if (OrigOLvl == CodeGenOpt::None)
return OrigOLvl;
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
Function *F = (Function *)I;
if (F->size() > FuncSizeThreshold) {
return CodeGenOpt::None;
}
}
return OrigOLvl;
}
int
llvmCodeGen(
Module* Composite,
amd::option::Options *OptionsObj,
std::string& output,
aclBinary* binary)
{
const FamilyMapping &familyMap = familySet[binary->target.arch_id];
const bool optimize = (OptionsObj ? (OptionsObj->oVariables->OptLevel > 0) : true);
const TargetMapping* targetMap = familyMap.target;
unsigned famID = binary->target.chip_id;
if (!targetMap || !targetMap[famID].supported) {
LogError("Device is not supported by code generator!");
return 1;
}
#if 1 || LLVM_TRUNK_INTEGRATION_CL >= 1463
#else
// a dirty way to guarantee "push bp" inserted by CodeGen in prologue
llvm::NoFramePointerElim = !optimize;
#endif
// Load the module to be compiled...
Module &mod = *Composite;
// FIXME: The triple given in this map is wrong and isn't really
// useful. Only need the architecture.
const std::string TargetTriple = std::string(familyMap.triple);
Triple TheTriple(TargetTriple);
if (TheTriple.getTriple().empty()) {
TheTriple.setTriple(sys::getDefaultTargetTriple());
}
Triple::ArchType arch = TheTriple.getArch();
bool isGPU = (arch == Triple::amdil || arch == Triple::amdil64 ||
arch == Triple::hsail || arch == Triple::hsail_64);
if (isGPU) {
TheTriple.setOS(Triple::UnknownOS);
} else { // CPUs
// FIXME: This should come from somewhere else.
#ifdef __linux__
TheTriple.setOS(Triple::Linux);
#else
TheTriple.setOS(Triple::MinGW32);
#endif
}
TheTriple.setEnvironment(Triple::AMDOpenCL);
// FIXME: need to make AMDOpenCL be the same as ELF
if (OptionsObj->oVariables->UseJIT)
TheTriple.setEnvironment(Triple::ELF);
mod.setTargetTriple(TheTriple.getTriple());
// Allocate target machine. First, check whether the user has explicitly
// specified an architecture to compile for. If so we have to look it up by
// name, because it might be a backend that has no mapping to a target triple.
const Target *TheTarget = 0;
assert(binary->target.arch_id != aclError && "Cannot have the error device!");
std::string MArch = familyMap.architecture;
#ifdef WITH_TARGET_HSAIL
if (MArch == "hsail" && OptionsObj->oVariables->GPU64BitIsa) {
MArch = std::string("hsail-64");
}
#endif
for (TargetRegistry::iterator it = TargetRegistry::begin(),
ie = TargetRegistry::end(); it != ie; ++it) {
if (MArch == it->getName()) {
TheTarget = &*it;
break;
}
}
if (!TheTarget) {
errs() << ": ERROR: invalid target '" << MArch << "'.\n";
return 1;
}
CodeGenOpt::Level OLvl = CodeGenOpt::None;
switch (OptionsObj->oVariables->OptLevel) {
case 0: // -O0
OLvl = CodeGenOpt::None;
break;
case 1: // -O1
OLvl = CodeGenOpt::Less;
break;
default:
assert(!"Error with optimization level");
case 2: // -O2
case 5: // -O5(-Os)
OLvl = CodeGenOpt::Default;
break;
case 3: // -O3
case 4: // -O4
OLvl = CodeGenOpt::Aggressive;
break;
};
// If there is a very big function, lower the optimization level.
OLvl = AdjustCGOptLevel(mod, OLvl);
// Adjust the triple to match (if known), otherwise stick with the
// module/host triple.
Triple::ArchType Type = Triple::getArchTypeForLLVMName(MArch);
if (Type != Triple::UnknownArch)
TheTriple.setArch(Type);
// Package up features to be passed to target/subtarget
std::string FeatureStr;
if ((Type == Triple::amdil || Type == Triple::amdil64) &&
targetMap[famID].chip_options) {
uint64_t y = targetMap[famID].chip_options;
for (uint64_t x = 0; y != 0; y >>= 1, ++x) {
if (!(y & 0x1) && (x >= 11 && x < 16)) {
continue;
}
if ((1 << x) == F_NO_ALIAS) {
FeatureStr += (!OptionsObj->oVariables->AssumeAlias ? '+' : '-');
} else if ((1 << x) == F_STACK_UAV) {
FeatureStr += (OptionsObj->oVariables->UseStackUAV ? '+' : '-');
} else if ((1 << x) == F_MACRO_CALL) {
FeatureStr += (OptionsObj->oVariables->UseMacroForCall ? '+' : '-');
} else if ((1 << x) == F_64BIT_PTR) {
FeatureStr += (binary->target.arch_id == aclAMDIL64) ? '+' : '-';
} else {
FeatureStr += ((y & 0x1) ? '+' : '-');
}
FeatureStr += GPUCodeGenFlagTable[x];
if (y != 0x1) {
FeatureStr += ',';
}
}
}
if (Type == Triple::amdil64) {
if (OptionsObj->oVariables->SmallGlobalObjects)
FeatureStr += ",+small-global-objects";
}
#if 1 || LLVM_TRUNK_INTEGRATION_CL >= 1463
llvm::TargetOptions targetOptions;
targetOptions.NoFramePointerElim = false;
targetOptions.StackAlignmentOverride =
OptionsObj->oVariables->CPUStackAlignment;
// jgolds
//targetOptions.EnableEBB = (optimize && OptionsObj->oVariables->CGEBB);
//targetOptions.EnableBFO = OptionsObj->oVariables->CGBFO;
//targetOptions.NoExcessFPPrecision = !OptionsObj->oVariables->EnableFMA;
// Don't allow unsafe optimizations for CPU because the library
// contains code that is not safe. See bug 9567.
if (isGPU)
targetOptions.UnsafeFPMath = OptionsObj->oVariables->UnsafeMathOpt;
targetOptions.LessPreciseFPMADOption = OptionsObj->oVariables->MadEnable ||
OptionsObj->oVariables->EnableMAD;
targetOptions.NoInfsFPMath = OptionsObj->oVariables->FiniteMathOnly;
// Need to add a support for OptionsObj->oVariables->NoSignedZeros,
targetOptions.NoNaNsFPMath = OptionsObj->oVariables->FastRelaxedMath;
std::auto_ptr<TargetMachine>
target(TheTarget->createTargetMachine(TheTriple.getTriple(),
aclGetCodegenName(binary->target), FeatureStr, targetOptions,
WINDOWS_SWITCH(Reloc::DynamicNoPIC, Reloc::PIC_),
CodeModel::Default, OLvl));
#else
std::auto_ptr<TargetMachine>
target(TheTarget->createTargetMachine(TheTriple.getTriple(),
aclGetCodegenName(binary->target), FeatureStr,
WINDOWS_SWITCH(Reloc::DynamicNoPIC, Reloc::PIC_),
CodeModel::Default));
assert(target.get() && "Could not allocate target machine!");
#endif
// MCJIT(Jan)
if(!isGPU && OptionsObj->oVariables->UseJIT) {
TargetMachine* jittarget(TheTarget->createTargetMachine(TheTriple.getTriple(),
aclGetCodegenName(binary->target), FeatureStr, targetOptions,
WINDOWS_SWITCH(Reloc::DynamicNoPIC, Reloc::PIC_),
CodeModel::Default, OLvl));
std::string ErrStr = jitCodeGen(Composite, jittarget, OLvl, output);
if (!ErrStr.empty()) {
LogError("MCJIT failed to generate code");
LogError(ErrStr.c_str());
return 1;
}
return 0;
}
TargetMachine &Target = *target;
// Figure out where we are going to send the output...
raw_string_ostream *RSOut = new raw_string_ostream(output);
formatted_raw_ostream *Out = new formatted_raw_ostream(*RSOut, formatted_raw_ostream::DELETE_STREAM);
if (Out == 0) {
LogError("llvmCodeGen couldn't create an output stream");
return 1;
}
// Build up all of the passes that we want to do to the module or function or
// Basic Block.
PassManager Passes;
// Add the target data from the target machine, if it exists, or the module.
if (const DataLayout *TD = Target.getDataLayout())
Passes.add(new DataLayout(*TD));
else
Passes.add(new DataLayout(&mod));
// Override default to generate verbose assembly, if the device is not the GPU.
// The GPU sets this in AMDILTargetMachine.cpp.
if (familyMap.target == (const TargetMapping*)&X86TargetMapping ||
#if WITH_VERSION_0_9
familyMap.target == (const TargetMapping*)&A32TargetMapping ||
familyMap.target == (const TargetMapping*)&A32TargetMapping ||
#elif WITH_VERSION_0_8
#else
#error "The current version implementation was not implemented here."
#endif
familyMap.target == (const TargetMapping*)&X64TargetMapping
) {
Target.setAsmVerbosityDefault(true);
}
#ifdef WITH_TARGET_HSAIL
if (isHSAILTarget(binary->target)) {
if (Target.addPassesToEmitFile(Passes, *Out, TargetMachine::CGFT_ObjectFile, true)) {
delete Out;
return 1;
}
} else
#endif
{
#ifndef NDEBUG
#if 1 || LLVM_TRUNK_INTEGRATION_CL >= 1144
if (Target.addPassesToEmitFile(Passes, *Out, TargetMachine::CGFT_AssemblyFile, false))
#else
if (Target.addPassesToEmitFile(Passes, *Out, TargetMachine::CGFT_AssemblyFile, OLvl, false))
#endif
#else
#if 1 || LLVM_TRUNK_INTEGRATION_CL >= 1144
if (Target.addPassesToEmitFile(Passes, *Out, TargetMachine::CGFT_AssemblyFile, true))
#else
if (Target.addPassesToEmitFile(Passes, *Out, TargetMachine::CGFT_AssemblyFile, OLvl, true))
#endif
#endif
{
delete Out;
return 1;
}
}
Passes.run(mod);
delete Out;
return 0;
}
int
CLCodeGen::codegen(llvm::Module *input)
{
uint64_t time_cg = 0ULL;
if (Options()->oVariables->EnableBuildTiming) {
time_cg = amd::Os::timeNanos();
}
llvmbinary_ = input;
amdcl::CompilerStage *cs = reinterpret_cast<amdcl::CompilerStage*>(this);
if (!isHSAILTarget(cs->Elf()->target)) {
setWholeProgram(true);
}
int ret = llvmCodeGen(LLVMBinary(), Options(), Source(), Elf());
if (Options()->oVariables->EnableBuildTiming) {
time_cg = amd::Os::timeNanos() - time_cg;
std::stringstream tmp_ss;
tmp_ss << " LLVM CodeGen time: "
<< time_cg/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
if (!Source().empty() && Options()->isDumpFlagSet(amd::option::DUMP_CGIL)) {
std::string ilFileName = Options()->getDumpFileName(".il");
std::fstream f;
f.open(ilFileName.c_str(), (std::fstream::out | std::fstream::binary));
f.write(Source().data(), Source().length());
f.close();
}
return ret;
}
@@ -0,0 +1,87 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_CODEGEN_HPP_
#define _BE_CODEGEN_HPP_
#include "compiler_stage.hpp"
namespace amdcl
{
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::CodeGen
*
* @{
*/
class CodeGen : public LLVMCompilerStage {
CodeGen(CodeGen&); // DO NOT IMPLEMENT.
CodeGen(); // DO NOT IMPLEMENT.
public:
CodeGen(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: LLVMCompilerStage(cl, elf, log) {}
virtual ~CodeGen() {}
/*! Function that takes in an LLVM module as input
* and generates code for it based on the target
* device.
* Returns 0 on success and non-zero on failure.
*/
virtual int codegen(llvm::Module *input) = 0;
}; // class CodeGen
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::CLCodeGen
*
* @{
*/
class CLCodeGen : public CodeGen {
CLCodeGen(CLCodeGen&); // DO NOT IMPLEMENT.
CLCodeGen(); // DO NOT IMPLEMENT.
public:
CLCodeGen(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: CodeGen(cl, elf, log) {}
virtual ~CLCodeGen() {}
/*! Function that takes in an LLVM module as input
* and generates code for it based on the target
* device.
* Returns 0 on success and non-zero on failure.
*/
virtual int codegen(llvm::Module *input);
}; // class CLCodeGen
/*@}*/
#if 0
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::AMDILCodeGen
*
* @{
*/
class AMDILCodeGen : public CodeGen {
AMDILCodeGen(AMDILCodeGen&); // DO NOT IMPLEMENT.
AMDILCodeGen(); // DO NOT IMPLEMENT.
public:
AMDILCodeGen(aclCompiler *cl, aclBinary *elf, llvm::LLVMContext *ctx)
: CLCodeGen(cl, elf, ctx) {}
virtual ~AMDILCodeGen() {}
/*! Function that takes in an LLVM module as input
* and generates code for it based on the target
* device.
* Returns 0 on success and non-zero on failure.
*/
int codegen(llvm::Module *input) = 0;
}; // class AMDILCodeGen
/*@}*/
#endif
} // amdcl namespace
#endif // _BE_CODEGEN_HPP_
@@ -0,0 +1,99 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#include "compiler_stage.hpp"
#include "utils/libUtils.h"
using namespace amdcl;
CompilerStage::CompilerStage(aclCompiler* cl, aclBinary* elf,
aclLogFunction callback)
: cl_(cl), elf_(elf), binary_(NULL),
source_(""), log_(""), callback_(callback)
{
opts_ = (amd::option::Options*)Elf()->options;
}
CompilerStage::~CompilerStage()
{ }
LLVMCompilerStage::LLVMCompilerStage(aclCompiler *cl, aclBinary *elf,
aclLogFunction callback)
: CompilerStage(cl, elf, callback),
llvmbinary_(NULL),
context_(NULL)
{
if (!Options()->oVariables->DisableAllWarnings) {
hookup_.LLVMBuildLog = &log_;
}
// Expose some options to LLVM.
llvm::AMDOptions *amdopts = &hookup_.amdoptions;
amdopts->OptLiveness = Options()->oVariables->OptLiveness;
if (isHSAILTarget(Elf()->target)) {
if ((amdopts->NumAvailGPRs == ~0u) || (Options()->NumAvailGPRs != -1))
amdopts->NumAvailGPRs = Options()->NumAvailGPRs;
} else {
amdopts->OptPrintLiveness = Options()->oVariables->OptPrintLiveness;
amdopts->OptMem2reg = Options()->oVariables->OptMem2reg;
amdopts->UseJIT = Options()->oVariables->UseJIT;
amdopts->APThreshold = Options()->oVariables->APThreshold;
amdopts->AAForBarrier = Options()->oVariables->AAForBarrier;
amdopts->UnrollScratchThreshold = 500;
amdopts->AmdilUseDefaultResId = Options()->oVariables->DefaultResourceId;
}
amdopts->OptSimplifyLibCall = Options()->oVariables->OptSimplifyLibCall;
amdopts->EnableFDiv2FMul = Options()->oVariables->EnableFDiv2FMul;
amdopts->SRThreshold = Options()->oVariables->SRThreshold;
amdopts->OptMemCombineMaxVecGen = Options()->oVariables->OptMemCombineMaxVecGen;
amdopts->OptLICM = Options()->oVariables->OptLICM;
// math-related options
amdopts->UnsafeMathOpt = Options()->oVariables->UnsafeMathOpt;
amdopts->NoSignedZeros = Options()->oVariables->NoSignedZeros;
amdopts->FiniteMathOnly = Options()->oVariables->FiniteMathOnly;
amdopts->FastRelaxedMath = Options()->oVariables->FastRelaxedMath;
amdopts->LUThreshold = Options()->oVariables->LUThreshold;
amdopts->LUCount = Options()->oVariables->LUCount;
amdopts->LUAllowPartial = Options()->oVariables->LUAllowPartial;
amdopts->GPUArch = (uint32_t)getLibraryType(&elf->target);
}
void
LLVMCompilerStage::setContext(aclContext *ctx)
{
context_ = reinterpret_cast<llvm::LLVMContext*>(ctx);
if (ctx) {
Context().setAMDLLVMContextHook(&hookup_);
}
}
LLVMCompilerStage::~LLVMCompilerStage()
{
if (context_) {
Context().setAMDLLVMContextHook(NULL);
}
}
llvm::Module*
LLVMCompilerStage::loadBitcode(std::string& llvmBinary)
{
if (!llvm::isBitcode(reinterpret_cast<const unsigned char*>(llvmBinary.data()),
reinterpret_cast<const unsigned char*>(llvmBinary.data()
+ llvmBinary.length()))) {
llvm::SMDiagnostic diags;
return ParseAssemblyString(llvmBinary.c_str(), llvmbinary_, diags, Context());
}
// Use getMemBuffer() ?
if (llvm::MemoryBuffer *Buffer =
llvm::MemoryBuffer::getMemBufferCopy(
llvm::StringRef(llvmBinary), "input.bc")) {
std::string ErrorMessage;
llvm::Module* M =
llvm::ParseBitcodeFile(Buffer, Context(), &ErrorMessage);
delete Buffer;
return M;
}
return NULL;
}
@@ -0,0 +1,96 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_COMPILER_STAGE_HPP_
#define _BE_COMPILER_STAGE_HPP_
#include "aclTypes.h"
#include "utils/options.hpp"
#include "llvm/AMDLLVMContextHook.h"
#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Assembly/Parser.h"
#include <cassert>
#include <string>
namespace amdcl
{
/*! \addtogroup CompilerLibrary
*
* \copydoc amdcl::CompilerStage
*
* @{
*/
class CompilerStage {
private:
CompilerStage(); // DO NOT IMPLEMENT.
CompilerStage(CompilerStage&); // DO NOT IMPLEMENT.
public:
CompilerStage(aclCompiler* cl, aclBinary* elf, aclLogFunction callback);
virtual ~CompilerStage();
/*! Returns the Compiler */
aclCompiler* CL() const { return cl_; }
/*! Returns the elf binary */
aclBinary* Elf() const { return elf_; }
/*! Returns the callback */
aclLogFunction Callback() const { return callback_; }
/*! Returns the options */
amd::option::Options* Options() const {
assert(opts_ && "Options should not be null");
return opts_;
}
/*! Returns the source file */
std::string& Source() { return source_; }
/*! Returns the build log */
std::string& BuildLog() { return log_; }
protected:
aclCompiler *cl_;
aclBinary *elf_;
void *binary_;
amd::option::Options* opts_;
std::string source_;
std::string log_;
aclLogFunction callback_;
}; // class CompilerStage
class LLVMCompilerStage : public CompilerStage {
public:
LLVMCompilerStage(aclCompiler *cl, aclBinary *elf,
aclLogFunction callback);
virtual ~LLVMCompilerStage();
void setContext(aclContext *ctx);
/*! Returns the local context */
llvm::LLVMContext& Context() { return (*context_); }
/*! Loads bitcode in either text or binary format and return
* and LLVM module. */
virtual llvm::Module* loadBitcode(std::string& llvmBinary);
void setGPU(bool isForGPU) { hookup_.amdoptions.IsGPU = isForGPU; }
void setWholeProgram(bool Val) { hookup_.amdoptions.WholeProgram = Val; }
/*! Returns the llvm binary */
llvm::Module* LLVMBinary() const { return llvmbinary_; }
aclModule* Module() const { return reinterpret_cast<aclModule*>(llvmbinary_);}
protected:
llvm::Module *llvmbinary_;
llvm::LLVMContext *context_;
llvm::AMDLLVMContextHook hookup_;
}; // class CompilerStage
/*@}*/
}
#endif // _BE_COMPILER_STAGE_HPP_
@@ -0,0 +1,295 @@
//
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "frontend.hpp"
#include "bif/bifbase.hpp"
#include "utils/libUtils.h"
#include "utils/target_mappings.h"
#include "utils/options.hpp"
#include "os/os.hpp"
#include "llvm/ADT/StringRef.h"
#include <cassert>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
bool Is64bitMachine() {return sizeof(void*) == 8;}
void
amdcl::OCLFrontend::appendCLVersionFlag(std::stringstream &ss,
const amd::option::Options *opts)
{
llvm::StringRef clStd(opts->oVariables->CLStd);
if (clStd == "CL1.0") {
ss << "--opencl=1.0 ";
} else if (clStd == "CL1.1") {
ss << "--opencl=1.1 ";
} else if (clStd == "CL1.2") {
ss << "--opencl=1.2 ";
} else {
if (clStd != "CL2.0") {
appendLogToCL(CL(), "Warning: invalid value for -cl-std, defaulting to CL1.2");
ss << "--opencl=1.2 ";
return;
}
ss << "--opencl=2.0 ";
}
}
///
/// @brief Function that converts elf + src combo into the correct
/// sequence of commands to call the CLC frontend.
///
/// FIXME: This needs to be modified so writing to a file is
/// not necessary!
std::string
amdcl::OCLFrontend::getFrontendCommand(aclBinary *elf,
const std::string &src,
std::string &logFile,
std::string &clFile,
bool preprocessOnly)
{
std::stringstream systemPath;
std::fstream f;
amd::option::Options* Opts = (amd::option::Options*)elf->options;
f.open(clFile.c_str(), (std::fstream::out | std::fstream::binary));
f.write(src.data(), src.length());
f.close();
bool enableSpir = false;
#ifdef DEBUG
enableSpir = getenv("AMD_OCL_ENABLE_SPIR");
#endif
if (enableSpir)
systemPath << "clc --spir --emit=spirbc ";
else
systemPath << "clc --emit=llvmbc ";
appendCLVersionFlag(systemPath, Opts);
if (enableSpir)
systemPath << "--amd-options-begin " << Opts->origOptionStr << " --amd-options-end ";
#if WITH_VERSION_0_8
if (checkFlag(aclutGetCaps(elf), capImageSupport)) {
systemPath << "-D__IMAGE_SUPPORT__=1 ";
}
if (checkFlag(aclutGetCaps(elf), capFMA)) {
systemPath << "-DFP_FAST_FMAF=1 ";
systemPath << "-DFP_FAST_FMA=1 ";
}
#elif WITH_VERSION_0_9
#else
#error "The current version was not handled correctly here."
#endif
// F_IMAGES
if (Options()->oVariables->ImageSupport) {
systemPath << "-D__IMAGE_SUPPORT__=1 ";
}
if (Options()->oVariables->FastFMA) {
systemPath << "-DFP_FAST_FMA=1 ";
}
if (Options()->oVariables->FastFMAF) {
systemPath << "-DFP_FAST_FMAF=1 ";
}
systemPath << "-D__AMD__=1 ";
uint32_t chipName = elf->target.chip_id;
assert(chipName < familySet[elf->target.arch_id].children_size && "Cannot index past end of array!");
switch(elf->target.arch_id) {
default:
assert(!"Unknown target device ID!");
case aclX64:
systemPath << "--march=x86-64 -D__X86_64__=1 -D__" << X64TargetMapping[chipName].chip_name << "__=1 ";
break;
case aclX86:
systemPath << "--march=x86 -D__X86__=1 -D__" << X86TargetMapping[chipName].chip_name << "__=1 ";
break;
case aclAMDIL:
systemPath << "-D__AMDIL__ -D__" << AMDILTargetMapping[chipName].chip_name << "__=1 ";
break;
case aclAMDIL64:
systemPath << "--march=gpu-64 -D__AMDIL_64__ -D__" << AMDIL64TargetMapping[chipName].chip_name << "__=1 ";
break;
#if WITH_VERSION_0_9
case aclA64:
systemPath << "--march=arm64 -D__ARM_64__=1 -D__" << A64TargetMapping[chipName].chip_name << "__=1 ";
break;
case aclARM:
systemPath << "--march=arm -D__ARM__=1 -D__" << A32TargetMapping[chipName].chip_name << "__=1 ";
break;
#elif WITH_VERSION_0_8
#else
#error "The current version was not handled correctly here."
#endif
case aclHSAIL:
systemPath << "--march=hsail -D__HSAIL__ -D__" << HSAILTargetMapping[chipName].chip_name << "__=1 ";
break;
case aclHSAIL64:
systemPath << "--march=hsail-64 -D__HSAIL__ -D__" << HSAIL64TargetMapping[chipName].chip_name << "__=1 ";
break;
};
// AMDIL and non CPU HSAIL targets get the GPU define, everything
// else gets CPU define.
if (!isCpuTarget(elf->target)) {
systemPath << "-D__GPU__=1 ";
} else {
systemPath << "-D__CPU__=1 ";
}
if (elf->target.arch_id == aclAMDIL
&& AMDILTargetMapping[chipName].family_enum == FAMILY_RV7XX) {
systemPath << "-Dcl_amd_vec3=1 -Dcl_amd_printf=1 --opencl=1.0";
}
if (Opts) {
systemPath << Opts->clcOptions;
}
#ifdef WITH_TARGET_HSAIL
if ((Is64bitMachine() && isHSAILTarget(elf->target)) ||
(Opts->oVariables->GPU64BitIsa && (elf->target.arch_id == aclHSAIL)))
systemPath << " --march=hsail-64 ";
#endif
#ifdef DEBUG
const char* env = getenv("AMD_EDG_OPTIONS");
if (env)
systemPath << env << " ";
#endif
#ifdef DEBUG
if (!getenv("AMD_OCL_SHOW_COMPILER_OUTPUT"))
#endif
systemPath << " --error_output \"" << logFile << "\" ";
if(preprocessOnly) {
std::string clppFileName = Opts->getDumpFileName(".i");
systemPath << " -E -o \"" << clppFileName << "\"";
}
systemPath << " \"" << clFile << "\" ";
LogPrintfDebug("Invoking CL to LLVM binary compilation:\n %s",
systemPath.str().c_str());
#ifdef DEBUG
if(getenv("AMD_OCL_SHOW_CMD_LINE"))
std::cout << "command line: " << systemPath.str() << std::endl;
#endif
if (Opts && Opts->isDumpFlagSet(amd::option::DUMP_CL) && !preprocessOnly) {
std::string clFileName = Opts->getDumpFileName(".cl");
f.open(clFileName.c_str(), (std::fstream::out | std::fstream::binary));
f.write(src.data(), src.length());
f.close();
}
std::string clcCmd = systemPath.str();
return clcCmd;
}
// CLC_IN_PROCESS_CHANGE
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);
static std::string
loadFileToStr(std::string file)
{
std::string str = "";
std::ifstream log(file.c_str(), std::ios::in|std::ios::ate);
if (log.is_open()) {
size_t size = (size_t)log.tellg();
log.seekg(0, std::ios::beg);
std::vector<char> buffer(size+1);
log.read(&buffer[0],size);
log.close();
//for safety
buffer[size] = '\0';
str += &buffer[0];
}
return str;
}
int
amdcl::OCLFrontend::compileCommand(const std::string& singleSrc)
{
std::string tempFileName = amd::Os::getTempFileName();
std::string logFile = tempFileName + ".log";
std::string clFile = tempFileName + ".cl";
std::string frontendCmd = getFrontendCommand(Elf(), singleSrc, logFile,
clFile, false);
std::string logStr;
uint64_t start_time = 0, stop_time = 0;
amd::option::Options* Opts = (amd::option::Options*)Elf()->options;
if (Options()->oVariables->EnableBuildTiming) {
start_time = amd::Os::timeNanos();
}
if (
#if WITH_VERSION_0_8
!checkFlag(aclutGetCaps(Elf()), capSaveSOURCE)
#elif WITH_VERSION_0_9
!Options()->oVariables->BinSOURCE
#else
#error "The current version was not handled correctly here."
#endif
) {
CL()->clAPI.remSec(CL(), Elf(), aclSOURCE);
}
int ret = openclFrontEnd(frontendCmd.c_str(), &Source(), NULL);
// We dump the preprocessed code by invoking clc a second time after the
// original call, just in case somthing really bad happens in the original
// call.
if (Opts && Opts->isDumpFlagSet(amd::option::DUMP_I)) {
std::string pplogFile = tempFileName + "preprocess.log";
std::string ppFrontendCmd =
getFrontendCommand(Elf(), singleSrc, pplogFile, clFile, true);
(void) openclFrontEnd(ppFrontendCmd.c_str(), &Source(), NULL);
amd::Os::unlink(pplogFile.c_str());
}
if (Options()->oVariables->EnableBuildTiming) {
stop_time = amd::Os::timeNanos();
std::stringstream tmp_ss;
tmp_ss << " OpenCL FE time: "
<< (stop_time - start_time)/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
llvmbinary_ = loadBitcode(Source());
if (!llvmbinary_) {
ret |= 1;
}
if (!ret &&
#if WITH_VERSION_0_8
checkFlag(aclutGetCaps(Elf()), capSaveLLVMIR)
#elif WITH_VERSION_0_9
Options()->oVariables->BinLLVMIR
#else
#error "The current version was not handled correctly here."
#endif
) {
CL()->clAPI.insSec(CL(), Elf(), Source().data(),
Source().size(), aclLLVMIR);
} else {
CL()->clAPI.remSec(CL(), Elf(), aclLLVMIR);
}
log_ += loadFileToStr(logFile);
amd::Os::unlink(logFile.c_str());
if (isCpuTarget(Elf()->target)
&& Options()->oVariables->EnableDebug) {
Options()->sourceFileName_ = clFile;
} else {
amd::Os::unlink(clFile.c_str());
}
return ret;
}
@@ -0,0 +1,99 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_FRONTEND_HPP_
#define _BE_FRONTEND_HPP_
#include <string>
#include "aclTypes.h"
#include "compiler_stage.hpp"
namespace amdcl
{
/*! \addtogroup CompilerLibrary
*
* \copydoc amdcl::Frontend
*
* @{
* \brief Interface parent class for the frontend child classes.
* This class should never be instantiated directly.
*/
class Frontend : public LLVMCompilerStage {
Frontend(Frontend&); // DO NOT IMPLEMENT.
Frontend(); // DO NOT IMPLEMENT.
public:
Frontend(aclCompiler* cl, aclBinary* elf, aclLogFunction log)
: LLVMCompilerStage(cl, elf, log) {}
//! Virtual destructer that makes sure everything is cleaned up.
virtual ~Frontend() {}
//! Function that converts from OpenCL singleSrc into
// OpenCL formatted LLVM-IR stored as a std::string.
// This function generates a command string for clc to execute.
virtual int compileCommand(const std::string& singleSrc) = 0;
}; // class Frontend
/*@}*/
/*! \addtogroup CompilerLibrary
*
* \copydoc amdcl::OCLFrontend
*
* @{
* \brief Implementation of the Frontend interface to compile
* from OpenCL C to LLVM-IR.
*/
class OCLFrontend : public Frontend {
OCLFrontend(OCLFrontend&); // DO NOT IMPLEMENT.
OCLFrontend(); // DO NOT IMPLEMENT.
void appendCLVersionFlag(
std::stringstream &ss,
const amd::option::Options *opts);
std::string getFrontendCommand(
aclBinary *elf,
const std::string &src,
std::string &logFile,
std::string &clFile,
bool preprocessOnly);
public:
OCLFrontend(aclCompiler* cl, aclBinary* elf, aclLogFunction log)
: Frontend(cl, elf, log) {}
virtual ~OCLFrontend() {}
//! Function that converts from OpenCL singleSrc into
// OpenCL formatted LLVM-IR stored as a std::string.
// This function generates a command string for clc to execute.
virtual int compileCommand(const std::string& singleSrc);
}; // class OCLFrontend
/*@}*/
/*! \addtogroup CompilerLibrary
*
* \copydoc amdcl::Frontend
*
* @{
* \brief This is the class which calls the clang front-end.
* This class will be used if user asks for it (By default EDG will be
* called).
*/
class ClangOCLFrontend : public Frontend {
//! Options to be passed to the ClangOCLFE library.
public:
ClangOCLFrontend(aclCompiler* cl, aclBinary* elf, aclLogFunction log);
//! Virtual destructer that makes sure everything is cleaned up.
virtual ~ClangOCLFrontend() {}
//! This function generates a command string for ClangOCLFE to execute.
virtual int compileCommand(const std::string& singleSrc);
}; // class Frontend
/*@}*/
} // namespac amdcl
#endif // _BE_FRONTEND_HPP_
@@ -0,0 +1,202 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "OpenCLFE.h"
#include "bif/bifbase.hpp"
#include "frontend.hpp"
#include "os/os.hpp"
#include "top.hpp"
#include "utils/libUtils.h"
#include "utils/options.hpp"
#include "utils/target_mappings.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <sstream>
#include <fstream>
amdcl::ClangOCLFrontend::ClangOCLFrontend(aclCompiler* cl, aclBinary* elf,
aclLogFunction log)
: Frontend(cl, elf, log){}
/// @brief This function generates the required command-line options to
/// call the ClangOCLFE library.
int amdcl::ClangOCLFrontend::compileCommand(const std::string& src) {
std::vector<const char*> argsToClang;
std::string tempFileName = amd::Os::getTempFileName();
std::string logFileName = tempFileName + ".log";
std::string inpCLFileName = tempFileName + ".cl";
std::string logFromClang;
int ret = 0;
aclBinary *elf = Elf();
amd::option::Options* amdOpts = (amd::option::Options*)elf->options;
// Following are the options passed to the ClangOCLFE library
// and then to Clang itself.
// Passing the compiler FE options to clang.
if (amdOpts) {
for (std::vector<std::string>::const_iterator it = amdOpts->clangOptions.begin();
it != amdOpts->clangOptions.end(); ++it) {
argsToClang.push_back((*it).c_str());
}
}
// Other options are passed using OptionsInfo structure.
clc2::OptionsInfo ClangOptions;
ClangOptions.InFilename = inpCLFileName;
// Generate target triple.
// TODO: Refine the triple as necessary.
uint32_t chipName = elf->target.chip_id;
assert(chipName < familySet[elf->target.arch_id].children_size &&
"Cannot index past end of array!");
switch (elf->target.arch_id) {
default:
log_ += "\nerror: Unknown target device ID!\n";
ret |= 1;
return ret;
break;
case aclX86:
case aclAMDIL:
case aclHSAIL:
// See bug: http://ocltc.amd.com/bugs/show_bug.cgi?id=9631
if (sizeof(void*) != 4) {
log_ += "\nerror: 32-bit kernels not supported on a 64-bit executable\n";
ret |= 1;
return ret;
}
ClangOptions.TargetArch = llvm::Triple::spir;
break;
case aclX64:
case aclAMDIL64:
case aclHSAIL64:
// See bug: http://ocltc.amd.com/bugs/show_bug.cgi?id=9631
if (sizeof(void*) != 8) {
log_ += "\nerror: 64-bit kernels not supported on a 32-bit executable\n";
ret |= 1;
return ret;
}
ClangOptions.TargetArch = llvm::Triple::spir64;
break;
};
// Copy the source to a buffer. Note that the input
// file itself is not passed to the ClangOCLFE library. It is a passed
// as a string for compilation.
llvm::MemoryBuffer *srcBuffer =
llvm::MemoryBuffer::getMemBuffer(src, inpCLFileName.c_str(),
true);
llvm::OwningPtr<llvm::MemoryBuffer> srcBufferPtr(srcBuffer);
ClangOptions.Src.swap(srcBufferPtr);
assert(ClangOptions.Src.get() && "ClangOCLFE: Memory Buffer"
" initialization error\n");
// Set Pre-processor output if user asks for it.
if (amdOpts && amdOpts->isDumpFlagSet(amd::option::DUMP_I)) {
ClangOptions.PreProcOut = amdOpts->getDumpFileName(".i");
}
// Set the LLVMContext for the front-end compilation.
ClangOptions.CompilerContext = &Context();
if (amdOpts && amdOpts->isDumpFlagSet(amd::option::DUMP_CL)) {
std::string inpCLFileName = amdOpts->getDumpFileName(".cl");
std::fstream f;
f.open(inpCLFileName.c_str(), (std::fstream::out | std::fstream::binary));
f.write(src.data(), src.length());
f.close();
}
//Start the compilation
uint64_t start_time = 0, stop_time = 0;
if (Options()->oVariables->EnableBuildTiming) {
start_time = amd::Os::timeNanos();
}
if (
#if WITH_VERSION_0_8
!checkFlag(aclutGetCaps(Elf()), capSaveSOURCE)
#elif WITH_VERSION_0_9
!Options()->oVariables->BinSOURCE
#else
#error "The current version was not handled correctly here."
#endif
) {
CL()->clAPI.remSec(CL(), Elf(), aclSOURCE);
}
// Pass OpenCL version option to Clang
llvm::StringRef OCLVer(amdOpts->oVariables->CLStd);
if (OCLVer.equals("CL1.2")) {
ClangOptions.OCLVer = clc2::OCL_12;
} else if (OCLVer.equals("CL2.0")) {
ClangOptions.OCLVer = clc2::OCL_20;
} else {
llvm_unreachable("Unknown OpenCL version");
}
// Call the Clang Front-end to generate serialized llvm::Module
// from the OpenCL source.
#ifdef ANDROID
// We will not exercise Clang for RenderScript.
log_ += "\nerror: Clang front-end compilation unsupported on Android!\n";
ret |= 1;
return ret;
#else
if (!parseOCLSource(ClangOptions, argsToClang, &Source(), &logFromClang)) {
log_ += logFromClang;
log_ += "\nerror: Clang front-end compilation failed!\n";
ret |= 1;
return ret;
}
#endif
if (Options()->oVariables->EnableBuildTiming) {
stop_time = amd::Os::timeNanos();
std::stringstream tmp_ss;
tmp_ss << " OpenCL FE time: "
<< (stop_time - start_time)/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
llvmbinary_ = loadBitcode(Source());
if (!llvmbinary_) {
ret |= 1;
}
if (!ret &&
#if WITH_VERSION_0_8
checkFlag(aclutGetCaps(Elf()), capSaveLLVMIR)
#elif WITH_VERSION_0_9
Options()->oVariables->BinLLVMIR
#else
#error "The current version was not handled correctly here."
#endif
) {
CL()->clAPI.insSec(CL(), Elf(), Source().data(),
Source().size(), aclLLVMIR);
} else {
CL()->clAPI.remSec(CL(), Elf(), aclLLVMIR);
}
log_ += logFromClang;
if (isCpuTarget(Elf()->target)
&& Options()->oVariables->EnableDebug) {
Options()->sourceFileName_ = inpCLFileName;
} else {
amd::Os::unlink(inpCLFileName.c_str());
}
return ret;
}
@@ -0,0 +1,15 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _IF_ACL_H_
#define _IF_ACL_H_
#include "aclTypes.h"
#if WITH_VERSION_0_8
#include "v0_8/if_acl.h"
#elif WITH_VERSION_0_9
#include "v0_9/if_acl.h"
#else
#error "The compiler library version was not defined."
#include "v0_8/if_acl.h"
#endif
#endif // _IF_ACL_H_
@@ -0,0 +1,290 @@
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include <vector>
#include <string>
#include "top.hpp"
#include "aclTypes.h"
#include "library.hpp"
#include "utils/options.hpp"
namespace amd {
/*
Integrated bitcode libraries
*/
// GPU libraries
#if defined(WITH_TARGET_AMDIL)
#include "builtins-gpugen-comm.inc"
#include "builtins-gpugen-diff.gpu.inc"
#include "builtins-gpugen-diff.gpu-64.inc"
#include "builtins-gpucommon-comm.inc"
#include "builtins-gpucommon-diff.gpu.inc"
#include "builtins-gpucommon-diff.gpu-64.inc"
#include "builtins-SI-comm.inc"
#include "builtins-SI-diff.gpu.inc"
#include "builtins-SI-diff.gpu-64.inc"
#include "builtins-CI-comm.inc"
#include "builtins-CI-diff.gpu.inc"
#include "builtins-CI-diff.gpu-64.inc"
#endif // WITH_TARGET_AMDIL
// CPU libraries
#if defined(WITH_TARGET_X86)
#include "builtins-cpugen.x86.inc"
#include "builtins-cpucommon.x86.inc"
#include "builtins-avx.x86.inc"
#include "builtins-fma4.x86.inc"
#include "builtins-cpugen.x86-64.inc"
#include "builtins-cpucommon.x86-64.inc"
#include "builtins-avx.x86-64.inc"
#include "builtins-fma4.x86-64.inc"
#endif // WITH_TARGET_X86
#if defined(WITH_TARGET_ARM)
#include "builtins-cpugen.arm.inc"
#include "builtins-cpucommon.arm.inc"
#endif // WITH_TARGET_ARM
#ifdef WITH_TARGET_HSAIL
// HSAIL libraries
#include "builtins-hsail.inc"
#include "builtins-hsail-amd-ci.inc"
#include "builtins-gcn.inc"
#endif
#include <cstdlib>
// getLibsDesc() : returns a list of libraries that need to be linked with the
// application. The max number of libraries is defined by
// enum MAX_NUM_LIBRARY_DESCS in class LibraryDescriptor.
//
// Return 0: successful
// <n>: error happened
int
getLibDescs (
LibrarySelector LibType, // input
LibraryDescriptor* LibDesc, // output
int& LibDescSize // output -- LibDesc[0:LibDescSize-1]
)
{
switch (LibType) {
#if defined(WITH_TARGET_AMDIL)
case GPU_Library_Evergreen:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>
(builtins_gpucommon_comm);
LibDesc[0].size = builtins_gpucommon_comm_size;
LibDesc[1].start = reinterpret_cast<const char*>
(builtins_gpucommon_diff_gpu);
LibDesc[1].size = builtins_gpucommon_diff_gpu_size;
LibDesc[2].start = reinterpret_cast<const char*>
(builtins_gpugen_comm);
LibDesc[2].size = builtins_gpugen_comm_size;
LibDesc[3].start = reinterpret_cast<const char*>
(builtins_gpugen_diff_gpu);
LibDesc[3].size = builtins_gpugen_diff_gpu_size;
LibDescSize = 4;
break;
case GPU_Library_SI:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>
(builtins_SI_comm);
LibDesc[0].size = builtins_SI_comm_size;
LibDesc[1].start = reinterpret_cast<const char*>
(builtins_SI_diff_gpu);
LibDesc[1].size = builtins_SI_diff_gpu_size;
LibDesc[2].start = reinterpret_cast<const char*>
(builtins_gpucommon_comm);
LibDesc[2].size = builtins_gpucommon_comm_size;
LibDesc[3].start = reinterpret_cast<const char*>
(builtins_gpucommon_diff_gpu);
LibDesc[3].size = builtins_gpucommon_diff_gpu_size;
LibDesc[4].start = reinterpret_cast<const char*>
(builtins_gpugen_comm);
LibDesc[4].size = builtins_gpugen_comm_size;
LibDesc[5].start = reinterpret_cast<const char*>
(builtins_gpugen_diff_gpu);
LibDesc[5].size = builtins_gpugen_diff_gpu_size;
LibDescSize = 6;
break;
case GPU64_Library_SI:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>
(builtins_SI_comm);
LibDesc[0].size = builtins_SI_comm_size;
LibDesc[1].start = reinterpret_cast<const char*>
(builtins_SI_diff_gpu_64);
LibDesc[1].size = builtins_SI_diff_gpu_64_size;
LibDesc[2].start = reinterpret_cast<const char*>
(builtins_gpucommon_comm);
LibDesc[2].size = builtins_gpucommon_comm_size;
LibDesc[3].start = reinterpret_cast<const char*>
(builtins_gpucommon_diff_gpu_64);
LibDesc[3].size = builtins_gpucommon_diff_gpu_64_size;
LibDesc[4].start = reinterpret_cast<const char*>
(builtins_gpugen_comm);
LibDesc[4].size = builtins_gpugen_comm_size;
LibDesc[5].start = reinterpret_cast<const char*>
(builtins_gpugen_diff_gpu_64);
LibDesc[5].size = builtins_gpugen_diff_gpu_64_size;
LibDescSize = 6;
break;
case GPU_Library_CI:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>
(builtins_CI_comm);
LibDesc[0].size = builtins_CI_comm_size;
LibDesc[1].start = reinterpret_cast<const char*>
(builtins_CI_diff_gpu);
LibDesc[1].size = builtins_CI_diff_gpu_size;
LibDesc[2].start = reinterpret_cast<const char*>
(builtins_SI_comm);
LibDesc[2].size = builtins_SI_comm_size;
LibDesc[3].start = reinterpret_cast<const char*>
(builtins_SI_diff_gpu);
LibDesc[3].size = builtins_SI_diff_gpu_size;
LibDesc[4].start = reinterpret_cast<const char*>
(builtins_gpucommon_comm);
LibDesc[4].size = builtins_gpucommon_comm_size;
LibDesc[5].start = reinterpret_cast<const char*>
(builtins_gpucommon_diff_gpu);
LibDesc[5].size = builtins_gpucommon_diff_gpu_size;
LibDesc[6].start = reinterpret_cast<const char*>
(builtins_gpugen_comm);
LibDesc[6].size = builtins_gpugen_comm_size;
LibDesc[7].start = reinterpret_cast<const char*>
(builtins_gpugen_diff_gpu);
LibDesc[7].size = builtins_gpugen_diff_gpu_size;
LibDescSize = 8;
break;
case GPU64_Library_CI:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>
(builtins_CI_comm);
LibDesc[0].size = builtins_CI_comm_size;
LibDesc[1].start = reinterpret_cast<const char*>
(builtins_CI_diff_gpu_64);
LibDesc[1].size = builtins_CI_diff_gpu_64_size;
LibDesc[2].start = reinterpret_cast<const char*>
(builtins_SI_comm);
LibDesc[2].size = builtins_SI_comm_size;
LibDesc[3].start = reinterpret_cast<const char*>
(builtins_SI_diff_gpu_64);
LibDesc[3].size = builtins_SI_diff_gpu_64_size;
LibDesc[4].start = reinterpret_cast<const char*>
(builtins_gpucommon_comm);
LibDesc[4].size = builtins_gpucommon_comm_size;
LibDesc[5].start = reinterpret_cast<const char*>
(builtins_gpucommon_diff_gpu_64);
LibDesc[5].size = builtins_gpucommon_diff_gpu_64_size;
LibDesc[6].start = reinterpret_cast<const char*>
(builtins_gpugen_comm);
LibDesc[6].size = builtins_gpugen_comm_size;
LibDesc[7].start = reinterpret_cast<const char*>
(builtins_gpugen_diff_gpu_64);
LibDesc[7].size = builtins_gpugen_diff_gpu_64_size;
LibDescSize = 8;
break;
#endif // WITH_TARGET_AMDIL
#if defined(WITH_TARGET_X86)
case CPU64_Library_Generic:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_cpucommon_x86_64);
LibDesc[0].size = builtins_cpucommon_x86_64_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_cpugen_x86_64);
LibDesc[1].size = builtins_cpugen_x86_64_size;
LibDescSize = 2;
break;
case CPU64_Library_AVX:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_avx_x86_64);
LibDesc[0].size = builtins_avx_x86_64_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_cpucommon_x86_64);
LibDesc[1].size = builtins_cpucommon_x86_64_size;
LibDesc[2].start = reinterpret_cast<const char*>(builtins_cpugen_x86_64);
LibDesc[2].size = builtins_cpugen_x86_64_size;
LibDescSize = 3;
break;
case CPU64_Library_FMA4:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_fma4_x86_64);
LibDesc[0].size = builtins_fma4_x86_64_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_avx_x86_64);
LibDesc[1].size = builtins_avx_x86_64_size;
LibDesc[2].start = reinterpret_cast<const char*>(builtins_cpucommon_x86_64);
LibDesc[2].size = builtins_cpucommon_x86_64_size;
LibDesc[3].start = reinterpret_cast<const char*>(builtins_cpugen_x86_64);
LibDesc[3].size = builtins_cpugen_x86_64_size;
LibDescSize = 4;
break;
case CPU_Library_Generic:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_cpucommon_x86);
LibDesc[0].size = builtins_cpucommon_x86_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_cpugen_x86);
LibDesc[1].size = builtins_cpugen_x86_size;
LibDescSize = 2;
break;
case CPU_Library_AVX:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_avx_x86);
LibDesc[0].size = builtins_avx_x86_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_cpucommon_x86);
LibDesc[1].size = builtins_cpucommon_x86_size;
LibDesc[2].start = reinterpret_cast<const char*>(builtins_cpugen_x86);
LibDesc[2].size = builtins_cpugen_x86_size;
LibDescSize = 3;
break;
case CPU_Library_FMA4:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_fma4_x86);
LibDesc[0].size = builtins_fma4_x86_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_avx_x86);
LibDesc[1].size = builtins_avx_x86_size;
LibDesc[2].start = reinterpret_cast<const char*>(builtins_cpucommon_x86);
LibDesc[2].size = builtins_cpucommon_x86_size;
LibDesc[3].start = reinterpret_cast<const char*>(builtins_cpugen_x86);
LibDesc[3].size = builtins_cpugen_x86_size;
LibDescSize = 4;
break;
#endif // WITH_TARGET_X86
#if defined(WITH_TARGET_ARM)
case CPU_Library_Generic:
LibDesc[0].start = reinterpret_cast<const char*>(builtins_cpucommon_arm);
LibDesc[0].size = builtins_cpucommon_arm_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_cpugen_arm);
LibDesc[1].size = builtins_cpugen_arm_size;
LibDescSize = 2;
break;
#endif // WITH_TARGET_ARM
#if defined(WITH_TARGET_HSAIL)
case GPU_Library_HSAIL:
// Library order is important!
LibDesc[0].start = reinterpret_cast<const char*>(builtins_gcn);
LibDesc[0].size = builtins_gcn_size;
LibDesc[1].start = reinterpret_cast<const char*>(builtins_hsail_amd_ci);
LibDesc[1].size = builtins_hsail_amd_ci_size;
LibDesc[2].start = reinterpret_cast<const char*>(builtins_hsail);
LibDesc[2].size = builtins_hsail_size;
LibDescSize = 3;
break;
#endif // WITH_TARGET_HSAIL
default:
// Failed
return 1; //
}
return 0;
}
} // namespace amd
@@ -0,0 +1,59 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef LIBRARY_H_
#define LIBRARY_H_
#include <vector>
#include <string>
namespace amd {
typedef enum _library_selector_0_7 {
LibraryUndefined = 0,
GPU_Library_7xx,
GPU_Library_Evergreen,
GPU_Library_SI,
CPU_Library_Generic,
CPU_Library_AVX,
CPU_Library_FMA4,
GPU_Library_Generic,
CPU64_Library_Generic,
CPU64_Library_AVX,
CPU64_Library_FMA4,
GPU64_Library_Evergreen,
GPU64_Library_SI,
GPU64_Library_Generic,
GPU_Library_CI,
GPU64_Library_CI,
GPU_Library_HSAIL,
LibraryTotal
} LibrarySelector;
/** Integrated Bitcode Libararies **/
class LibraryDescriptor {
public:
enum {MAX_NUM_LIBRARY_DESCS = 11};
const char* start;
size_t size;
};
int getLibDescs (
LibrarySelector LibType, // input
LibraryDescriptor* LibDesc, // output
int& LibDescSize // output -- LibDesc[0:LibDescSize-1]
);
static const char* amdRTFuns[] = {
"__amdrt_div_i64",
"__amdrt_div_u64",
"__amdrt_mod_i64",
"__amdrt_mod_u64",
"__amdrt_cvt_f64_to_u64",
"__amdrt_cvt_f32_to_u64"
};
} //amd
#endif // LIBRARY_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,103 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_LINKER_HPP_
#define _BE_LINKER_HPP_
#include "compiler_stage.hpp"
#include "aclTypes.h"
#include <string>
#include <map>
namespace llvm {
class Module;
class Value;
}; // namespace llvm
namespace amdcl
{
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::Linker
*
* @{
*/
class Linker : public LLVMCompilerStage{
Linker(Linker&); // DO NOT IMPLEMENT.
Linker(); // DO NOT IMPLEMENT.
public:
Linker(aclCompiler *cl, aclBinary* elf, aclLogFunction log)
: LLVMCompilerStage(cl, elf, log) {}
virtual ~Linker() {}
/*! Function that takes as in a llvm::Module that contains LLVM-IR
* binary and links in a vector of libraries.
* Returns 0 on success, non-zero on failure.
*/
virtual int link(llvm::Module* input, std::vector<llvm::Module*> &libs) = 0;
}; // class Linker
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::OCLLinker
*
* @{
* \brief Linker that is unique to OpenCL.
*/
class OCLLinker : public Linker {
enum {
MASK_NO_SIGNED_ZEROES = 0x1,
MASK_UNSAFE_MATH_OPTIMIZATIONS = 0x2,
MASK_FINITE_MATH_ONLY = 0x4,
MASK_FAST_RELAXED_MATH = 0x8,
MASK_UNIFORM_WORK_GROUP_SIZE = 0x10
};
public:
OCLLinker(aclCompiler* cl, aclBinary* bin, aclLogFunction log)
: Linker(cl, bin, log) {}
virtual ~OCLLinker() {
for (unsigned j = 0, i = (unsigned)mathLibs_.size(); j < i; ++j) {
if (mathLibs_[j]) {
delete mathLibs_[j];
}
}
};
void setPreLinkOpt(bool Val) { hookup_.amdoptions.IsPreLinkOpt = Val; }
void setUnrollScratchThreshold(uint32_t ust) { hookup_.amdoptions.UnrollScratchThreshold = ust; }
bool getWholeProgram() { return hookup_.amdoptions.WholeProgram; }
uint32_t getUnrollScratchThreshold() { return hookup_.amdoptions.UnrollScratchThreshold; }
/*! Function that takes as input a std::string which
* contains LLVM-IR binary and links in a vector of libraries.
* This version also links in the OpenCL math libraries along with
* the list of libraries that are passed in.
*/
int link(llvm::Module* input, std::vector<llvm::Module*> &libs);
protected:
void createOptionMaskFunction(llvm::Module* module);
void createASICIDFunctions(llvm::Module* module);
bool linkLLVMModules(std::vector<llvm::Module*> &libs);
bool linkWithModule(llvm::Module* Dst, llvm::Module* Src,
std::map<const llvm::Value*, bool> *ModuleRefMap);
private:
static void fixupOldTriple(llvm::Module* module);
/*! Vector of modules that stores the math libraries.
*/
std::vector<llvm::Module*> mathLibs_;
}; // class OCLLinker
/*@}*/
}; // namespace amdcl
#endif // _BE_LINKER_HPP_
@@ -0,0 +1,186 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "opt_level.hpp"
#include "library.hpp"
#include "utils/options.hpp"
#include "llvm/Module.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/DataLayout.h"
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
#include "llvm/LinkAllPasses.h"
#include "llvm/Transforms/IPO/AMDOptOptions.h"
#include "compiler_stage.hpp"
using namespace amdcl;
using namespace llvm;
void
OptLevel::setup(bool isGPU, uint32_t OptLevel)
{
// Add an appropriate DataLayout instance for this module.
Passes().add(new DataLayout(module_));
fpasses_ = new FunctionPassManager(module_);
fpasses_->add(new DataLayout(module_));
PassManagerBuilder Builder;
Builder.OptLevel = OptLevel;
if (Options()->libraryType_ == amd::GPU_Library_HSAIL) {
if (OptLevel == 0) return;
}
if (!Options()->oVariables->Inline) {
// No inlining pass
} else if (isGPU) {
#ifdef WITH_TARGET_HSAIL
if (Options()->libraryType_ == amd::GPU_Library_HSAIL) {
if (HLC_Experimental_Enable_Calls) {
HLC_Disable_Amd_Inline_All = true;
}
// Always create Inliner regardless of OptLevel
if (HLC_Force_Always_Inliner_Pass) {
Builder.Inliner = createAlwaysInlinerPass();
} else {
Builder.Inliner = createFunctionInliningPass(500);
}
} else
#endif
{
// Always create Inliner regardless of OptLevel
Builder.Inliner = createFunctionInliningPass(500);
}
} else if (OptLevel > 1) {
unsigned Threshold = 225;
if (OptLevel > 2)
Threshold = 275;
#ifdef WITH_TARGET_HSAIL
if (Options()->libraryType_ == amd::GPU_Library_HSAIL) {
// Don't do inlining (including createAlwaysInlinerPass()) if OptimizationLevel
// is zero becaue we are generating code for -g
if (OptLevel > 0) {
Builder.Inliner = createFunctionInliningPass(Threshold);
}
} else
#endif
{
Builder.Inliner = createFunctionInliningPass(Threshold);
}
}
Builder.SizeLevel = 0;
Builder.DisableUnitAtATime = false;
Builder.DisableUnrollLoops = OptLevel == 0;
if (Options()->libraryType_ != amd::GPU_Library_HSAIL)
Builder.DisableSimplifyLibCalls = true;
Builder.AMDpopulateFunctionPassManager(*fpasses_, &module_->getContext());
Builder.AMDpopulateModulePassManager(passes_, &module_->getContext(), module_);
}
void
OptLevel::run()
{
if (Options()->oVariables->OptPrintLiveness) {
Passes().add(createAMDLivenessPrinterPass());
}
fpasses_->doInitialization();
for (Module::iterator I = module_->begin(), E = module_->end(); I != E; ++I)
fpasses_->run(*I);
fpasses_->doFinalization();
// Now that we have all of the passes ready, run them.
passes_.run(*module_);
delete fpasses_;
}
int
O0OptLevel::optimize(Module *input, bool isGPU)
{
// With -O0, we don't do anything
module_ = input;
#ifdef WITH_TARGET_HSAIL
if (Options()->libraryType_ == amd::GPU_Library_HSAIL) {
// Mark all non-kernel functions as having internal linkage
Passes().add(createAMDSymbolLinkagePass(true, NULL));
} else
#endif
{
setup(false, 0);
run();
}
return 0;
}
int
GPUO0OptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
assert(isGPU && "Only a GPU can use GPUO0OptLevel!\n");
setup(true, 0);
#ifdef WITH_TARGET_HSAIL
if (Options()->libraryType_ == amd::GPU_Library_HSAIL) {
// On the GPU, even with -O0, we must do some optimizations. One
// goal is to ensure that all functions are inlined. This requires
// three steps in that order:
//
// 1. Mark all non-kernel functions as having internal linkage.
// 2. Invoke the GlobalOptimizer to resolve function aliases.
// 3. Force inlining using our custom inliner pass.
Passes().add(createAMDSymbolLinkagePass(true, NULL));
Passes().add(createGlobalOptimizerPass());
if (!HLC_Disable_Amd_Inline_All && !DisableInline ) {
if (HLC_Force_Always_Inliner_Pass) {
Passes().add(createAlwaysInlinerPass());
} else {
Passes().add(createAMDInlineAllPass(true));
}
}
}
#endif
run();
return 0;
}
int
O1OptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
setup(isGPU, 1);
run();
return 0;
}
int
O2OptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
setup(isGPU, 2);
run();
return 0;
}
int
O3OptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
setup(isGPU, 3);
run();
return 0;
}
int
O4OptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
setup(isGPU, 4);
run();
return 0;
}
int
OsOptLevel::optimize(Module *input, bool isGPU)
{
module_ = input;
setup(isGPU, 5);
run();
return 0;
}
@@ -0,0 +1,188 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_OPT_LEVEL_HPP_
#define _BE_OPT_LEVEL_HPP_
#include "top.hpp"
#include "utils/options.hpp"
#include "llvm/PassManager.h"
#include "llvm/Analysis/Passes.h"
namespace llvm {
class Module;
class FunctionPassManager;
}; // llvm namespace
namespace amdcl
{
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::OptLevel
*
* @{
*/
class OptLevel {
OptLevel(OptLevel&); // DO NOT IMPLEMENT.
OptLevel(); // DO NOT IMPLEMENT.
public:
OptLevel(amd::option::Options *OptionsObj)
: opts_(OptionsObj) {}
virtual ~OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU) = 0;
protected:
void setup(bool isGPU, uint32_t OptLevel);
void run();
llvm::PassManager& Passes() { return passes_; }
llvm::FunctionPassManager& FPasses() { return (*fpasses_); }
amd::option::Options* Options() { return opts_; }
llvm::Module* module_;
private:
llvm::FunctionPassManager *fpasses_;
llvm::PassManager passes_;
amd::option::Options *opts_;
}; // class OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::O0OptLevel
*
* @{
*/
class O0OptLevel : public OptLevel {
O0OptLevel(O0OptLevel&); // DO NOT IMPLEMENT.
O0OptLevel(); // DO NOT IMPLEMENT.
public:
O0OptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~O0OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O0OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::GPUO0OptLevel
*
* @{
*/
class GPUO0OptLevel : public O0OptLevel {
GPUO0OptLevel(GPUO0OptLevel&); // DO NOT IMPLEMENT.
GPUO0OptLevel(); // DO NOT IMPLEMENT.
public:
GPUO0OptLevel(amd::option::Options *opts)
: O0OptLevel(opts) {}
virtual ~GPUO0OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O0OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::O1OptLevel
*
* @{
*/
class O1OptLevel : public OptLevel {
O1OptLevel(O1OptLevel&); // DO NOT IMPLEMENT.
O1OptLevel(); // DO NOT IMPLEMENT.
public:
O1OptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~O1OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O1OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::O2OptLevel
*
* @{
*/
class O2OptLevel : public OptLevel {
O2OptLevel(O2OptLevel&); // DO NOT IMPLEMENT.
O2OptLevel(); // DO NOT IMPLEMENT.
public:
O2OptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~O2OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O2OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::O3OptLevel
*
* @{
*/
class O3OptLevel : public OptLevel {
O3OptLevel(O3OptLevel&); // DO NOT IMPLEMENT.
O3OptLevel(); // DO NOT IMPLEMENT.
public:
O3OptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~O3OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O3OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::O4OptLevel
*
* @{
*/
class O4OptLevel : public OptLevel {
O4OptLevel(O4OptLevel&); // DO NOT IMPLEMENT.
O4OptLevel(); // DO NOT IMPLEMENT.
public:
O4OptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~O4OptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class O4OptLevel
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::OsOptLevel
*
* @{
*/
class OsOptLevel : public OptLevel {
OsOptLevel(OsOptLevel&); // DO NOT IMPLEMENT.
OsOptLevel(); // DO NOT IMPLEMENT.
public:
OsOptLevel(amd::option::Options *opts)
: OptLevel(opts) {}
virtual ~OsOptLevel() {}
virtual int optimize(llvm::Module *input, bool isGPU);
}; // class OsOptLevel
/*@}*/
}; // amdcl namespace
#endif // _BE_OPT_LEVEL_HPP_
@@ -0,0 +1,152 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "optimizer.hpp"
#include "opt_level.hpp"
#include "os/os.hpp"
#include "utils/bif_section_labels.hpp"
#include "utils/libUtils.h"
#include "utils/options.hpp"
#include "llvm/DataLayout.h"
#include "llvm/Analysis/Passes.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/LinkAllPasses.h"
#include <cassert>
#include <sstream>
using namespace amdcl;
using namespace llvm;
static OptLevel* getOptLevel(amd::option::Options* Options, bool isGPU) {
switch(Options->oVariables->OptLevel) {
case amd::option::OPT_O0:
return (isGPU) ? new GPUO0OptLevel(Options) : new O0OptLevel(Options);
case amd::option::OPT_O1:
return new O1OptLevel(Options);
default:
assert(!"Found an invalid optimization level!");
case amd::option::OPT_O2:
return new O2OptLevel(Options);
case amd::option::OPT_O3:
return new O3OptLevel(Options);
case amd::option::OPT_O4:
return new O4OptLevel(Options);
case amd::option::OPT_OS:
return new OsOptLevel(Options);
}
assert(!"Unreachable!");
return NULL;
}
int
CPUOptimizer::preOptimizer(llvm::Module* M)
{
llvm::PassManager Passes;
Passes.add(new llvm::DataLayout(M));
Passes.add(createAMDExportKernelNaturePass());
Passes.run(*M);
return 0;
}
int
CPUOptimizer::optimize(llvm::Module *input)
{
if (!input) {
return 1;
}
int ret = 0;
uint64_t start_time = 0ULL, time_opt = 0ULL;
llvmbinary_ = input;
setWholeProgram(true);
setGPU(false);
if (Options()->oVariables->EnableBuildTiming) {
start_time = amd::Os::timeNanos();
}
ret = preOptimizer(LLVMBinary());
OptLevel* cpuOpt = getOptLevel(Options(), false);
if (Options()->oVariables->EnableBuildTiming) {
time_opt = amd::Os::timeNanos();
}
ret = cpuOpt->optimize(LLVMBinary(), false);
if (Options()->oVariables->EnableBuildTiming) {
time_opt = amd::Os::timeNanos() - time_opt;
std::stringstream tmp_ss;
tmp_ss << " LLVM Opt time: "
<< time_opt/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
delete cpuOpt;
if ( ret ) {
BuildLog() += "Internal Error: optimizer failed!\n";
return 1;
}
if (Options()->isDumpFlagSet(amd::option::DUMP_BC_OPTIMIZED)) {
std::string MyErrorInfo;
std::string fileName = Options()->getDumpFileName("_optimized.bc");
raw_fd_ostream outs (fileName.c_str(), MyErrorInfo, raw_fd_ostream::F_Binary);
// FIXME: Need to add this to the elf binary!
if (MyErrorInfo.empty())
WriteBitcodeToFile(LLVMBinary(), outs);
else
printf(MyErrorInfo.c_str());
}
return ret;
}
int
GPUOptimizer::optimize(llvm::Module *input)
{
if (!input) {
return 1;
}
int ret = 0;
uint64_t start_time = 0ULL, time_opt = 0ULL;
llvmbinary_ = input;
setGPU(true);
setWholeProgram(true);
#ifdef WITH_TARGET_HSAIL
if (isHSAILTarget(Elf()->target)) {
if (Options()->NumAvailGPRs == -1)
Options()->NumAvailGPRs = 128; // Default HSAIL number of GPRs
if (hookup_.amdoptions.NumAvailGPRs == ~0u)
hookup_.amdoptions.NumAvailGPRs = Options()->NumAvailGPRs;
}
#endif
OptLevel* gpuOpt = getOptLevel(Options(), true);
if (Options()->oVariables->EnableBuildTiming) {
time_opt = amd::Os::timeNanos();
}
ret = gpuOpt->optimize(LLVMBinary(), true);
if (Options()->oVariables->EnableBuildTiming) {
time_opt = amd::Os::timeNanos() - time_opt;
std::stringstream tmp_ss;
tmp_ss << " LLVM Opt time: "
<< time_opt/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
delete gpuOpt;
if ( ret ) {
BuildLog() += "Internal Error: optimizer failed!\n";
return 1;
}
if (Options()->isDumpFlagSet(amd::option::DUMP_BC_OPTIMIZED)) {
std::string MyErrorInfo;
std::string fileName = Options()->getDumpFileName("_optimized.bc");
raw_fd_ostream outs (fileName.c_str(), MyErrorInfo, raw_fd_ostream::F_Binary);
// FIXME: Need to add this to the elf binary!
if (MyErrorInfo.empty())
WriteBitcodeToFile(LLVMBinary(), outs);
else
printf(MyErrorInfo.c_str());
}
return ret;
}
@@ -0,0 +1,106 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_OPTIMIZER_HPP_
#define _BE_OPTIMIZER_HPP_
#include "aclTypes.h"
#include "compiler_stage.hpp"
#include "llvm/Module.h"
namespace amdcl
{
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::Optimizer
*
* @{
*/
class Optimizer : public LLVMCompilerStage {
Optimizer(Optimizer&); // DO NOT IMPLEMENT.
Optimizer(); // DO NOT IMPLEMENT.
public:
Optimizer(aclCompiler *cl, aclBinary* elf, aclLogFunction log)
: LLVMCompilerStage(cl, elf, log) {
// Expose some options to LLVM
llvm::AMDOptions *amdopts = &hookup_.amdoptions;
if (opts_) {
amdopts->OptLiveness = opts_->oVariables->OptLiveness;
amdopts->NumAvailGPRs = opts_->NumAvailGPRs;
}
}
virtual ~Optimizer() {}
/*! Function that takes in the LLVM module as input
* and optimizes it.
* Returns 0 on success and non-zero on failure.
*/
virtual int optimize(llvm::Module *input) = 0;
}; // class Optimizer
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::CLOptimizer
*
* @{
*/
class CLOptimizer : public Optimizer {
public:
CLOptimizer(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: Optimizer(cl, elf, log) {}
virtual ~CLOptimizer() {}
/*! Function that takes in the LLVM module as input
* and optimizes it.
* Returns 0 on success and non-zero on failure.
*/
virtual int optimize(llvm::Module *input) = 0;
}; // class CLOptimizer
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::GPUOptimizer
*
* @{
*/
class GPUOptimizer : public CLOptimizer {
public:
GPUOptimizer(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: CLOptimizer(cl, elf, log) {}
virtual ~GPUOptimizer() {}
/*! Function that takes in the LLVM module as input
* and optimizes it.
* Returns 0 on success and non-zero on failure.
*/
virtual int optimize(llvm::Module *input);
}; // class GPUOptimizer
/*@}*/
/*! \addtogroup Compiler Library
*
* \copydoc amdcl::CPUOptimizer
*
* @{
*/
class CPUOptimizer : public CLOptimizer {
public:
CPUOptimizer(aclCompiler *cl, aclBinary *elf, aclLogFunction log)
: CLOptimizer(cl, elf, log) {}
virtual ~CPUOptimizer() {}
/*! Function that takes in the LLVM module as input
* and optimizes it.
* Returns 0 on success and non-zero on failure.
*/
virtual int optimize(llvm::Module *input);
protected:
int preOptimizer(llvm::Module *m);
}; // class CPUOptimizer
/*@}*/
}; // amdcl namespace
#endif // _BE_OPTIMIZER_HPP_
@@ -0,0 +1,138 @@
//
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
//
#include "top.hpp"
#include "spir.hpp"
#include "aclTypes.h"
#include "bif/bifbase.hpp"
#include "utils/libUtils.h"
#include "utils/options.hpp"
#include "utils/target_mappings.h"
#include "os/os.hpp"
#include <cassert>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include "llvm/DataLayout.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Analysis/SPIRVerifier.h"
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/Bitcode/BitstreamWriter.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Scalar.h"
using namespace llvm;
using namespace amdcl;
Module*
amdcl::SPIR::loadSPIR(std::string &spirBinary)
{
// Need to use the namespace here since a parent function is called Module().
llvm::Module *bc = NULL;
std::string errors;
source_ = spirBinary;
SPIRState State = {"", "", 1, 0, 1, 2};
bc = amdcl::LLVMCompilerStage::loadBitcode(source_);
if (!bc)
{
errors = "loadBitcode failed";
log_ += errors;
return NULL;
}
verifyModule(*bc, ReturnStatusAction, &errors);
if (!errors.empty()) {
log_ += errors;
errors.clear();
}
FunctionPassManager FPM(bc);
if (Options()->oVariables->verifyHWSpir) {
if (!isHSAILTarget(Elf()->target)) {
verifySPIRModule(*bc, ReturnStatusAction, State, false, &errors);
}
if (!errors.empty()) {
log_ += errors;
errors.clear();
delete bc;
return NULL;
}
}
if (Options()->oVariables->verifyLWSpir) {
if (!isHSAILTarget(Elf()->target)) {
verifySPIRModule(*bc, ReturnStatusAction, State, true, &errors);
}
if (!errors.empty()) {
log_ += errors;
errors.clear();
delete bc;
return NULL;
}
}
return bc;
}
Module*
amdcl::SPIR::loadBitcode(std::string &binary)
{
llvm::Module *bc = loadSPIR(binary);
if (!bc) return NULL;
// FIXME: It is not clear why SPIRLoader is invoked so early here.
// The current view is to keep SPIRLoader as a pure pre-link pass to
// be called only by the linker.
StringRef LayoutStr = is64BitTarget(Elf()->target) ?
DATA_LAYOUT_64BIT : DATA_LAYOUT_32BIT;
bc->setDataLayout(LayoutStr);
bc->setTargetTriple(familySet[Elf()->target.arch_id].triple);
llvm::PassManager SPIRPasses;
SPIRPasses.add(new llvm::DataLayout(bc));
SPIRPasses.add(createSPIRLoader(/*demangleBuiltin=*/ true));
SPIRPasses.run(*bc);
return bc;
}
const void*
SPIR::toBinary(const void *text, size_t text_size, size_t *binary_size)
{
std::string text_buf(reinterpret_cast<const char*>(text), text_size);
// Need to use the namespace here since a parent function is called Module().
llvm::Module *mod = loadSPIR(text_buf);
SmallString<256> char_buf;
raw_svector_ostream outstream(char_buf);
WriteBitcodeToFile(mod, outstream);
std::string str_buf(char_buf.begin(), char_buf.end());
(*binary_size) = char_buf.size();
void *ptr = aclutAlloc(CL())(*binary_size);
std::copy(char_buf.begin(), char_buf.end(), reinterpret_cast<char*>(ptr));
return ptr;
}
const void*
SPIR::toText(const void *binary, size_t binary_size, size_t *text_size)
{
std::string text_buf(reinterpret_cast<const char*>(binary), binary_size);
// Need to use the namespace here since a parent function is called Module().
llvm::Module *mod = loadSPIR(text_buf);
std::string errors;
if (!mod)
{
errors = "loadSPIR failed";
log_ += errors;
return NULL;
}
std::string bin_buf;
raw_string_ostream buf(bin_buf);
mod->print(buf, NULL);
(*text_size) = bin_buf.size();
void *ptr = aclutAlloc(CL())(*text_size);
std::copy(bin_buf.begin(), bin_buf.end(), reinterpret_cast<char*>(ptr));
return ptr;
}
@@ -0,0 +1,40 @@
//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _BE_SPIR_HPP_
#define _BE_SPIR_HPP_
#include <string>
#include "aclTypes.h"
#include "compiler_stage.hpp"
namespace amdcl
{
/*@}*/
/*! \addtogroup CompilerLibrary
*
* \copydoc amdcl::SPIR
*
* @{
* \brief Implementation of the Frontend interface to compile
* from OpenCL C to LLVM-IR.
*/
class SPIR : public LLVMCompilerStage {
SPIR(SPIR&); // DO NOT IMPLEMENT.
SPIR(); // DO NOT IMPLEMENT.
public:
SPIR(aclCompiler* cl, aclBinary* elf, aclLogFunction log)
: LLVMCompilerStage(cl, elf, log) {}
virtual ~SPIR() {}
virtual llvm::Module* loadBitcode(std::string &spirBinary);
virtual llvm::Module* loadSPIR(std::string &spirBinary);
const void*
toBinary(const void *text, size_t text_size, size_t *binary_size);
const void*
toText(const void *binary, size_t binary_size, size_t *text_size);
}; // class SPIR
/*@}*/
} // namespac amdcl
#endif // _BE_SPIR_HPP_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,129 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _IF_ACL_0_8_H_
#define _IF_ACL_0_8_H_
#include "aclTypes.h"
aclLoaderData* ACL_API_ENTRY
if_aclCompilerInit(aclCompiler *cl, aclBinary *bin, aclLogFunction log, acl_error *error);
acl_error ACL_API_ENTRY
if_aclCompilerFini(aclLoaderData *ald);
acl_error ACL_API_ENTRY
if_aclCompile(aclCompiler *cl,
aclBinary *bin,
const char *options,
aclType from,
aclType to,
aclLogFunction compile_callback) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclLink(aclCompiler *cl,
aclBinary *src_bin,
unsigned int num_libs,
aclBinary **libs,
aclType link_mode,
const char *options,
aclLogFunction link_callback) ACL_API_0_8;
const char* ACL_API_ENTRY
if_aclGetCompilerLog(aclCompiler *cl) ACL_API_0_8;
const void* ACL_API_ENTRY
if_aclRetrieveType(aclCompiler *cl,
const aclBinary *bin,
const char *name,
size_t *data_size,
aclType type,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclSetType(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type,
const void *data,
size_t size) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclConvertType(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclDisassemble(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
aclLogFunction disasm_callback) ACL_API_0_8;
const void* ACL_API_ENTRY
if_aclGetDeviceBinary(aclCompiler *cl,
const aclBinary *bin,
const char *kernel,
size_t *size,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclInsertSection(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclInsertSymbol(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id,
const char *symbol) ACL_API_0_8;
const void* ACL_API_ENTRY
if_aclExtractSection(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
acl_error *error_code) ACL_API_0_8;
const void* ACL_API_ENTRY
if_aclExtractSymbol(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
const char *symbol,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclRemoveSection(aclCompiler *cl,
aclBinary *binary,
aclSections id) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclRemoveSymbol(aclCompiler *cl,
aclBinary *binary,
aclSections id,
const char *symbol) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclQueryInfo(aclCompiler *cl,
const aclBinary *binary,
aclQueryType query,
const char *kernel,
void *data_ptr,
size_t *ptr_size) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclDbgAddArgument(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
const char *name,
bool byVal) ACL_API_0_8;
acl_error ACL_API_ENTRY
if_aclDbgRemoveArgument(aclCompiler *cl,
aclBinary *bin,
const char* kernel,
const char* name) ACL_API_0_8;
#endif // _IF_ACL_0_8_H_
@@ -0,0 +1,84 @@
include $(OPENCL_DEPTH)/opencldefs
COMPLIB_DEPTH = $(OPENCL_DEPTH)/compiler/lib
ifdef GONE_TO_BUILD_DIR
ifeq ($(BUILD_HSA_TARGET),yes)
override BUILD_CPU_DEVICE = no
override BUILD_GPU_DEVICE = no
endif
endif
ifneq ($(BUILD_GPU_DEVICE),no)
GCPPFLAGS += $(DEFSWITCH) WITH_TARGET_AMDIL
endif
ifneq ($(BUILD_HSA_DEVICE),no)
GCPPFLAGS += $(DEFSWITCH) WITH_TARGET_HSAIL
ifneq ($(BUILD_GPU_DEVICE),no)
GCPPFLAGS += $(DEFSWITCH) DYNAMIC_HSAIL
endif
endif
ifneq ($(BUILD_CPU_DEVICE),no)
ifdef ATI_ARCH_ARM
GCPPFLAGS += $(DEFSWITCH) WITH_TARGET_ARM
endif
ifdef ATI_ARCH_X86
ifneq ($(BUILD_CPU_DEVICE),no)
GCPPFLAGS += $(DEFSWITCH) WITH_TARGET_X86
endif
endif
endif
GCPPFLAGS += $(INCSWITCH) "$(DEPTH)/drivers"
GCPPFLAGS += $(INCSWITCH) "$(DEPTH)/drivers/inc/asic_reg"
GCPPFLAGS += $(INCSWITCH) "$(COMPLIB_DEPTH)"
GCPPFLAGS += $(INCSWITCH) "$(COMPLIB_DEPTH)/promotions/oclutils"
GCPPFLAGS += $(INCSWITCH) "$(COMPLIB_DEPTH)/utils"
# Do we build the 0.9 version?
ifeq ($(BUILD_VERSION_0_9), 1)
GCPPFLAGS += $(DEFSWITCH) WITH_VERSION_0_9
CLVER_SUBDIR = v0_9
else
# Otherwise we build v0.8
GCPPFLAGS += $(DEFSWITCH) WITH_VERSION_0_8
CLVER_SUBDIR = v0_8
endif
GCPPFLAGS += $(INCSWITCH) "$(COMPLIB_DEPTH)/utils/$(CLVER_SUBDIR)"
GCPPFLAGS += $(INCSWITCH) "$(COMPLIB_DEPTH)/include/$(CLVER_SUBDIR)"
GCPPFLAGS += $(DEFSWITCH) "BREAK_ON_LOG_WARNING=0"
GCPPFLAGS += $(DEFSWITCH) "BREAK_ON_LOG_ERROR=0"
GCPPFLAGS += $(DEFSWITCH) "LOG_LEVEL=2"
export CAL_INCLUDES = $(OPENCL_DEPTH)/runtime/device/gpu/gslbe/src/include/cal
GCPPFLAGS += $(INCSWITCH) "$(CAL_INCLUDES)"
GCPPFLAGS += $(INCSWITCH) "$(CAL_INCLUDES)/private"
GCPPFLAGS += $(INCSWITCH) "$(UGL_DEPTH)/gl/gs/hwl/pele/include/asic"
GCPPFLAGS += $(INCSWITCH) "$(UGL_DEPTH)/gl/gs/hwl/evergreen/include/asic"
GCPPFLAGS += $(INCSWITCH) "$(UGL_DEPTH)/gl/gs/hwl/si/include/asic"
export BRIG_ENABLE=1
ifdef ATI_OS_WINDOWS
GCPPFLAGS += $(INCSWITCH) "$(DK_ROOT)/$(DK_DX_SDK)/inc"
ifeq ($(BUILD_TYPE),dbg)
GCXXOPTS += /Ob1
endif
GCXXOPTS += -wd4985 -wd4355 -wd4800
GCPPFLAGS += $(DEFSWITCH) _SCL_SECURE_NO_WARNINGS
GCXXOPTS += /GR- # Disable Run-Time Type Information
endif
ifdef ATI_OS_LINUX
GCPPFLAGS += $(DEFSWITCH) __STDC_LIMIT_MACROS
GCPPFLAGS += $(DEFSWITCH) __STDC_CONSTANT_MACROS
GCXXOPTS += -fno-rtti
endif
@@ -0,0 +1,16 @@
COMPLIB_DEPTH = $(OPENCL_DEPTH)/compiler/lib
ifdef GONE_TO_BUILD_DIR
ifdef ATI_OS_LINUX
*$(OBJ_EXT): $(COMPLIB_DEPTH)/complibdefs $(COMPLIB_DEPTH)/complibrules
endif
endif
%.v08:
@$(MAKENOISE) "Setting BUILD_VERSION_0_8=1"
@$(MAKE) BUILD_VERSION_0_8=1 $*
%.v09:
@$(MAKENOISE) "Setting BUILD_VERSION_0_9=1"
@$(MAKE) BUILD_VERSION_0_9=1 $*
include $(OPENCL_DEPTH)/openclrules
@@ -0,0 +1,17 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_H_
#define ACL_H_
#if WITH_VERSION_0_8
#include "v0_8/acl.h"
#elif WITH_VERSION_0_9
#include "v0_9/acl.h"
#else
#error "The compiler library version was not defined."
#include "v0_8/acl.h"
#endif
#endif // ACL_H_
@@ -0,0 +1,16 @@
//
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_DEFS_H_
#define ACL_DEFS_H_
#if WITH_VERSION_0_8
#include "v0_8/aclDefs.h"
#elif WITH_VERSION_0_9
#else
#error "The compiler library version was not defined."
#include "v0_8/aclDefs.h"
#endif
#endif // ACL_DEFS_H_
@@ -0,0 +1,16 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_ENUMS_H_
#define ACL_ENUMS_H_
#if WITH_VERSION_0_8
#include "v0_8/aclEnums.h"
#elif WITH_VERSION_0_9
#else
#error "The compiler library version was not defined."
#include "v0_8/aclEnums.h"
#endif
#endif // ACL_ENUMS_H_
@@ -0,0 +1,16 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_FUNCTORS_H_
#define ACL_FUNCTORS_H_
#if WITH_VERSION_0_8
#include "v0_8/aclFunctors.h"
#elif WITH_VERSION_0_9
#else
#error "The compiler library version was not defined."
#include "v0_8/aclFunctors.h"
#endif
#endif // ACL_FUNCTORS_H_
@@ -0,0 +1,16 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_STRUCTS_H_
#define ACL_STRUCTS_H_
#if WITH_VERSION_0_8
#include "v0_8/aclStructs.h"
#elif WITH_VERSION_0_9
#else
#error "The compiler library version was not defined."
#include "v0_8/aclStructs.h"
#endif
#endif // ACL_STRUCTS_H_
@@ -0,0 +1,17 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
// This is a compatibility header file. Either define the version
// of the compiler library that is to be used or include the
// header file for that version directly.
#ifndef ACL_TYPES_H_
#define ACL_TYPES_H_
#if WITH_VERSION_0_8
#include "v0_8/aclTypes.h"
#elif WITH_VERSION_0_9
#include "v0_9/aclTypes.h"
#else
#error "The compiler library version was not defined."
#include "v0_8/aclTypes.h"
#endif
#endif // ACL_TYPES_H_
@@ -0,0 +1,250 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_0_8_H_
#define _ACL_0_8_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "aclTypes.h"
//!--------------------------------------------------------------------------!//
// Functions that deal with aclCompiler objects.
//!--------------------------------------------------------------------------!//
aclCompiler* ACL_API_ENTRY
aclCompilerInit(aclCompilerOptions *opts, acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclCompilerFini(aclCompiler *cl) ACL_API_0_8;
aclCLVersion ACL_API_ENTRY
aclCompilerVersion(aclCompiler *cl, acl_error *error_code) ACL_API_0_8;
uint32_t ACL_API_ENTRY
aclVersionSize(aclCLVersion num, acl_error *error_code) ACL_API_0_8;
const char* ACL_API_ENTRY
aclGetErrorString(acl_error error_code) ACL_API_0_8;
//!--------------------------------------------------------------------------!//
// Functions that deal with target specific information.
//!--------------------------------------------------------------------------!//
//! Returns in the names argument, if non-NULL, a pointer to each of the arch
// names that the compiler supports. If names is NULL and arch_size is
// non-NULL, returns the number of arch entries that are required.
acl_error ACL_API_ENTRY
aclGetArchInfo(const char** arch_names,
size_t *arch_size) ACL_API_0_8;
//! Returns in the arch argument, if non-NULL, a pointer to each device
// name that the compiler supports. If device_size is non-NULL,
// returns the number of device entries that are used.
acl_error ACL_API_ENTRY
aclGetDeviceInfo(const char* arch,
const char **names,
size_t *device_size) ACL_API_0_8;
//! Function that returns a correctly filled out aclTargetInfo structure based
// on the information passed into the kernel.
aclTargetInfo ACL_API_ENTRY
aclGetTargetInfo(const char *arch,
const char *device,
acl_error *error_code) ACL_API_0_8;
//! Function that returns a correctly filled out aclTargetInfo structure based
// on the information passed into the kernel.
aclTargetInfo ACL_API_ENTRY
aclGetTargetInfoFromChipID(const char *arch,
const uint32_t chip_id,
acl_error *error_code) ACL_API_0_8;
//! Function that returns a string representation of the target architecture.
const char* ACL_API_ENTRY
aclGetArchitecture(const aclTargetInfo &target) ACL_API_0_8;
//! Function that returns a string representation of the target chip options.
const uint64_t ACL_API_ENTRY
aclGetChipOptions(const aclTargetInfo &target) ACL_API_0_8;
//! Function that returns a string representation of the target family.
const char* ACL_API_ENTRY
aclGetFamily(const aclTargetInfo &target) ACL_API_0_8;
//! Function that returns a string representation of the target chip.
const char* ACL_API_ENTRY
aclGetChip(const aclTargetInfo &target) ACL_API_0_8;
//!--------------------------------------------------------------------------!//
// Functions that deal with aclBinary objects.
//!--------------------------------------------------------------------------!//
aclBinary* ACL_API_ENTRY
aclBinaryInit(
size_t struct_version,
const aclTargetInfo *target,
const aclBinaryOptions *options,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclBinaryFini(aclBinary *bin) ACL_API_0_8;
aclBinary* ACL_API_ENTRY
aclReadFromFile(const char *str,
acl_error *error_code) ACL_API_0_8;
aclBinary* ACL_API_ENTRY
aclReadFromMem(const void *mem,
size_t size, acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclWriteToFile(aclBinary *bin,
const char *str) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclWriteToMem(aclBinary *bin,
void **mem, size_t *size) ACL_API_0_8;
aclBinary* ACL_API_ENTRY
aclCreateFromBinary(const aclBinary *binary,
aclBIFVersion version) ACL_API_0_8;
aclBIFVersion ACL_API_ENTRY
aclBinaryVersion(const aclBinary *binary) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclInsertSection(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclInsertSymbol(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id,
const char *symbol) ACL_API_0_8;
const void* ACL_API_ENTRY
aclExtractSection(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
acl_error *error_code) ACL_API_0_8;
const void* ACL_API_ENTRY
aclExtractSymbol(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
const char *symbol,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclRemoveSection(aclCompiler *cl,
aclBinary *binary,
aclSections id) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclRemoveSymbol(aclCompiler *cl,
aclBinary *binary,
aclSections id,
const char *symbol) ACL_API_0_8;
//!--------------------------------------------------------------------------!//
// Functions that deal with debug/metdata.
//!--------------------------------------------------------------------------!//
acl_error ACL_API_ENTRY
aclQueryInfo(aclCompiler *cl,
const aclBinary *binary,
aclQueryType query,
const char *kernel,
void *data_ptr,
size_t *ptr_size) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclDbgAddArgument(aclCompiler *cl,
aclBinary *binary,
const char* kernel,
const char* name,
bool byVal)
ACL_API_0_8;
acl_error ACL_API_ENTRY
aclDbgRemoveArgument(aclCompiler *cl,
aclBinary *binary,
const char* kernel,
const char* name)
ACL_API_0_8;
//!--------------------------------------------------------------------------!//
// Functions that deal with various compilation phases.
//!--------------------------------------------------------------------------!//
acl_error ACL_API_ENTRY
aclCompile(aclCompiler *cl,
aclBinary *bin,
const char *options,
aclType from,
aclType to,
aclLogFunction compile_callback) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclLink(aclCompiler *cl,
aclBinary *src_bin,
unsigned int num_libs,
aclBinary **libs,
aclType link_mode,
const char *options,
aclLogFunction link_callback) ACL_API_0_8;
const char* ACL_API_ENTRY
aclGetCompilerLog(aclCompiler *cl) ACL_API_0_8;
const void* ACL_API_ENTRY
aclRetrieveType(aclCompiler *cl,
const aclBinary *bin,
const char *name,
size_t *data_size,
aclType type,
acl_error *error_code) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclSetType(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type,
const void *data,
size_t size) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclConvertType(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type) ACL_API_0_8;
acl_error ACL_API_ENTRY
aclDisassemble(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
aclLogFunction disasm_callback) ACL_API_0_8;
const void* ACL_API_ENTRY
aclGetDeviceBinary(aclCompiler *cl,
const aclBinary *bin,
const char *kernel,
size_t *size,
acl_error *error_code) ACL_API_0_8;
//!--------------------------------------------------------------------------!//
// Debug functionality
//!--------------------------------------------------------------------------!//
void aclDumpBinary(const aclBinary *bin);
//!--------------------------------------------------------------------------!//
// Functions that deal with memory.
// Free memory allocated by aclWriteToMem
//!--------------------------------------------------------------------------!//
acl_error ACL_API_ENTRY
aclFreeMem(aclBinary *bin,
void *mem);
#ifdef __cplusplus
}
#endif
#endif // _ACL_0_8_H_
@@ -0,0 +1,35 @@
//
// Copyright (c) 2011 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_DEFS_0_8_H_
#define _ACL_DEFS_0_8_H_
#ifndef ACL_API_ENTRY
#if defined(_WIN32) || defined(__CYGWIN__)
#define ACL_API_ENTRY __stdcall
#else
#define ACL_API_ENTRY
#endif
#endif
#ifndef ACL_API_0_8
#define ACL_API_0_8
#endif
#ifndef AOC_API_0_7
#define AOC_API_0_7
#endif
#ifndef BIF_API_2_0
#define BIF_API_2_0
#endif
#ifndef BIF_API_2_1
#define BIF_API_2_1
#endif
#ifndef BIF_API_3_0
#define BIF_API_3_0
#endif
#endif // _ACL_DEFS_0_8_H_
@@ -0,0 +1,318 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_ENUMS_0_8_H_
#define _ACL_ENUMS_0_8_H_
typedef enum _acl_error_enum_0_8 {
ACL_SUCCESS = 0,
ACL_ERROR = 1,
ACL_INVALID_ARG = 2,
ACL_OUT_OF_MEM = 3,
ACL_SYS_ERROR = 4,
ACL_UNSUPPORTED = 5,
ACL_ELF_ERROR = 6,
ACL_INVALID_FILE = 7,
ACL_INVALID_COMPILER= 8,
ACL_INVALID_TARGET = 9,
ACL_INVALID_BINARY = 10,
ACL_INVALID_OPTION = 11,
ACL_INVALID_TYPE = 12,
ACL_INVALID_SECTION = 13,
ACL_INVALID_SYMBOL = 14,
ACL_INVALID_QUERY = 15,
ACL_FRONTEND_FAILURE= 16,
ACL_INVALID_BITCODE = 17,
ACL_LINKER_ERROR = 18,
ACL_OPTIMIZER_ERROR = 19,
ACL_CODEGEN_ERROR = 20,
ACL_ISAGEN_ERROR = 21,
ACL_INVALID_SOURCE = 22,
ACL_LIBRARY_ERROR = 23,
ACL_INVALID_SPIR = 24,
ACL_LWVERIFY_FAIL = 25,
ACL_HWVERIFY_FAIL = 26,
ACL_LAST_ERROR = 27
} acl_error_0_8;
typedef enum _comp_device_caps_enum_0_8 {
capError = 0,
capFMA = 1,
capImageSupport = 2,
capSaveSOURCE = 3, // input source
capSaveLLVMIR = 4, // output LLVMIR from frontend
capSaveCG = 5, // output from LLVM-BE
capSaveEXE = 6, // output executable
capSaveAMDIL = 7, // Save per-kernel AMDIL
capSaveHSAIL = 8, // Save per-kernel HSAIL
capEncrypted = 9,
capSaveDISASM = 10,
capSaveAS = 11,
capSaveSPIR = 12,
capDumpLast = 13
} compDeviceCaps_0_8;
typedef enum _comp_opt_settings_enum_0_8 {
optO0 = 0, // No optimization setting.
optO1 = 1,
optO2 = 2,
optO3 = 3,
optO4 = 4,
optOs = 5,
optError = 6, // Invalid optimization set
optLast = 7
} compOptSettings_0_8;
#define FLAG_SHIFT_VALUE 5
#define FLAG_MASK_VALUE ((1 << capDumpLast) - 1)
#define FLAG_BITLOC(A) (1 << ((A) & FLAG_MASK_VALUE))
#define FLAG_ARRAY_SIZE 4
//! An enumeration that defines the possible valid device types that
// can be compiled for.
typedef enum _acl_dev_type_enum_0_8 {
aclError = 0, // aclDevType of 0 is an error.
aclX86 = 1, // Targeting a 32bit X86 CPU device.
aclAMDIL = 2, // Targeting an AMDIL GPU device.
aclHSAIL = 3, // Targeting an HSAIL GPU device.
aclX64 = 4, // Targeting a 64bit X86 CPU device.
aclHSAIL64= 5, // Targeting a 64bit HSAIL GPU device.
aclAMDIL64= 6, // Targeting a 64bit AMDIL GPU device
aclLast = 7
} aclDevType_0_8;
//! Enum that represents the versions of the compiler
typedef enum _acl_cl_version_enum_0_8 {
ACL_VERSION_ERROR = 0,
ACL_VERSION_0_7 = 1,
ACL_VERSION_0_8 = 2,
ACL_VERSION_0_8_1 = 3,
ACL_VERSION_0_9 = 4,
ACL_VERSION_1_0 = 5,
ACL_VERSION_LAST = 6
} aclCLVersion_0_8;
//! Enum of the various aclTypes that are supported
typedef enum _acl_type_enum_0_8 {
ACL_TYPE_DEFAULT = 0,
ACL_TYPE_OPENCL = 1,
ACL_TYPE_LLVMIR_TEXT = 2,
ACL_TYPE_LLVMIR_BINARY = 3,
ACL_TYPE_SPIR_TEXT = 4,
ACL_TYPE_SPIR_BINARY = 5,
ACL_TYPE_AMDIL_TEXT = 6,
ACL_TYPE_AMDIL_BINARY = 7,
ACL_TYPE_HSAIL_TEXT = 8,
ACL_TYPE_HSAIL_BINARY = 9,
ACL_TYPE_X86_TEXT = 10,
ACL_TYPE_X86_BINARY = 11,
ACL_TYPE_CG = 12,
ACL_TYPE_SOURCE = 13,
ACL_TYPE_ISA = 14,
ACL_TYPE_HEADER = 15,
ACL_TYPE_RSLLVMIR_BINARY = 16,
ACL_TYPE_LAST = 17
} aclType_0_8;
//! Enum of the various loader types that are supported.
typedef enum _acl_loader_type_enum_0_8 {
ACL_LOADER_COMPLIB = 0,
ACL_LOADER_FRONTEND = 1,
ACL_LOADER_LINKER = 2,
ACL_LOADER_OPTIMIZER= 3,
ACL_LOADER_CODEGEN = 4,
ACL_LOADER_BACKEND = 5,
ACL_LOADER_SC = 6,
ACL_LOADER_LAST = 7
} aclLoaderType_0_8;
// Enumeration for the various acl versions
typedef enum _bif_version_enum_0_8 {
aclBIFVersionError = 0, // Error
aclBIFVersion20 = 1, // Version 2.0 of the OpenCL BIF
aclBIFVersion21 = 2, // Version 2.1 of the OpenCL BIF
aclBIFVersion30 = 3, // Version 3.0 of the OpenCL BIF
aclBIFVersionLatest = aclBIFVersion30, // Most recent version of the BIF
aclBIFVersionCAL = 4,
aclBIFVersionLast = 5
} aclBIFVersion_0_8;
// Enumeration for the various platform types
typedef enum _bif_platform_enum_0_8 {
aclPlatformCAL = 0, // For BIF 2.0 backward compatibility
aclPlatformCPU = 1, // For BIF 2.0 backward compatibility
aclPlatformCompLib = 2,
aclPlatformLast = 3
} aclPlatform_0_8;
// Enumeration for the various bif sections
typedef enum _bif_sections_enum_0_8 {
aclLLVMIR = 0,
aclSOURCE = 1,
aclILTEXT = 2, // For BIF 2.0 backward compatibility
aclASTEXT = 3, // For BIF 2.0 backward compatibility
aclCAL = 4, // For BIF 2.0 backward compatibility
aclDLL = 5, // For BIF 2.0 backward compatibility
aclSTRTAB = 6,
aclSYMTAB = 7,
aclRODATA = 8,
aclSHSTRTAB = 9,
aclNOTES = 10,
aclCOMMENT = 11,
aclILDEBUG = 12, // For BIF 2.0 backward compatibility
aclDEBUG_INFO = 13,
aclDEBUG_ABBREV = 14,
aclDEBUG_LINE = 15,
aclDEBUG_PUBNAMES = 16,
aclDEBUG_PUBTYPES = 17,
aclDEBUG_LOC = 18,
aclDEBUG_ARANGES = 19,
aclDEBUG_RANGES = 20,
aclDEBUG_MACINFO = 21,
aclDEBUG_STR = 22,
aclDEBUG_FRAME = 23,
aclJITBINARY = 24, // For BIF 2.0 backward compatibility
aclCODEGEN = 25,
aclTEXT = 26,
aclINTERNAL = 27,
aclSPIR = 28,
aclHEADER = 29,
aclBRIGcode = 30,
aclBRIGdirs = 31,
aclBRIGoprs = 32,
aclBRIGstrs = 33,
aclHSADEBUG = 34,
aclLAST = 35
} aclSections_0_8;
//! An enumeration that defines what are valid queries for aclQueryInfo.
typedef enum _rt_query_types_enum_0_8 {
RT_ABI_VERSION = 0,
RT_DEVICE_NAME = 1,
RT_MEM_SIZES = 2,
RT_GPU_FUNC_CAPS = 3,
RT_GPU_FUNC_ID = 4,
RT_GPU_DEFAULT_ID = 5,
RT_WORK_GROUP_SIZE = 6,
RT_WORK_REGION_SIZE = 7,
RT_ARGUMENT_ARRAY = 8,
RT_GPU_PRINTF_ARRAY = 9,
RT_CPU_BARRIER_NAMES= 10,
RT_DEVICE_ENQUEUE = 11,
RT_KERNEL_INDEX = 12,
RT_LAST_TYPE = 13
} aclQueryType_0_8;
//! An enumeration for the various GPU capabilities
typedef enum _rt_gpu_caps_enum_0_8 {
RT_COMPILER_WRITE = 1 << 0,
RT_DATA_SECTION = 1 << 1,
RT_WGS = 1 << 2,
RT_LIMIT_WGS = 1 << 3,
RT_PACKED_REGS = 1 << 4,
RT_64BIT_ABI = 1 << 5,
RT_PRINTF = 1 << 6,
RT_ARENA_UAV = 1 << 7,
RT_LRP_MEM = 1 << 8, // Local/Region/Private Memory
RT_INDEX_TEMPS = 1 << 9,
RT_WRS = 1 << 10,
RT_GWS = 1 << 11,
RT_SWGWS = 1 << 12,
RT_GPU_CAPS_MASK = 0xFFF
} aclGPUCaps_0_8;
//! An enumeration for the various CPU capabilities.
typedef enum _rt_cpu_caps_enum_0_8 {
RT_KERNEL_BARRIER = 1 << 0,
RT_PROGRAM_BARRIER = 1 << 1,
RT_CPU_CAPS_MASK = 0x3
} aclCPUCaps_0_8;
//! An enumeration that maps Resource type to index values
typedef enum _rt_gpu_resource_enum_0_8 {
RT_RES_UAV = 0, // UAV resources
RT_RES_PRI = 1, // Private resources
RT_RES_LDS = 2, // LDS resources
RT_RES_GDS = 3, // GDS resources
RT_RES_CON = 4, // Constant resources
RT_RES_LAST = 5
} aclGPUResource_0_8;
//! An enumeration that maps memory types to index values
typedef enum _rt_gpu_mem_sizes_enum_0_8 {
RT_MEM_HW_LOCAL = 0,
RT_MEM_SW_LOCAL = 1,
RT_MEM_HW_PRIVATE = 2,
RT_MEM_SW_PRIVATE = 3,
RT_MEM_HW_REGION = 4,
RT_MEM_SW_REGION = 5,
RT_MEM_LAST = 6
} aclGPUMemSizes_0_8;
// Enumerations for the various argument types.
typedef enum _acl_arg_type_enum_0_8 {
ARG_TYPE_ERROR = 0,
ARG_TYPE_SAMPLER = 1,
ARG_TYPE_IMAGE = 2,
ARG_TYPE_COUNTER = 3,
ARG_TYPE_VALUE = 4,
ARG_TYPE_POINTER = 5,
ARG_TYPE_SEMAPHORE = 6,
ARG_TYPE_LAST = 7
} aclArgType_0_8;
// Enumerations of the valid data types for pass by value and
// pass by pointer kernel arguments.
typedef enum _acl_data_type_enum_0_8 {
DATATYPE_ERROR = 0,
DATATYPE_i1 = 1,
DATATYPE_i8 = 2,
DATATYPE_i16 = 3,
DATATYPE_i32 = 4,
DATATYPE_i64 = 5,
DATATYPE_u8 = 6,
DATATYPE_u16 = 7,
DATATYPE_u32 = 8,
DATATYPE_u64 = 9,
DATATYPE_f16 = 10,
DATATYPE_f32 = 11,
DATATYPE_f64 = 12,
DATATYPE_f80 = 13,
DATATYPE_f128 = 14,
DATATYPE_struct = 15,
DATATYPE_union = 16,
DATATYPE_event = 17,
DATATYPE_opaque = 18,
DATATYPE_unknown = 19,
DATATYPE_LAST = 20
} aclArgDataType_0_8;
// Enumerations of the valid memory types for pass by pointer
// kernel arguments
typedef enum _acl_memory_type_enum_0_8 {
PTR_MT_ERROR = 0, // Error
PTR_MT_GLOBAL = 1, // global buffer
PTR_MT_SCRATCH_EMU = 2, // SW emulated private memory
PTR_MT_LDS_EMU = 3, // SW emulated local memory
PTR_MT_UAV = 4, // uniformed access vector memory
PTR_MT_CONSTANT_EMU = 5, // SW emulated constant memory
PTR_MT_GDS_EMU = 6, // SW emulated region memory
PTR_MT_LDS = 7, // HW local memory
PTR_MT_SCRATCH = 8, // HW private memory
PTR_MT_CONSTANT = 9, // HW constant memory
PTR_MT_GDS = 10, // HW region memory
PTR_MT_UAV_SCRATCH = 11, // SI and later HW private memory
PTR_MT_UAV_CONSTANT = 12, // SI and later HW constant memory
PTR_MT_LAST = 13
} aclMemoryType_0_8;
// Enumeration that specifies the various access types for a pointer/image.
typedef enum _acl_access_type_enum_0_8 {
ACCESS_TYPE_ERROR = 0,
ACCESS_TYPE_RO = 1,
ACCESS_TYPE_WO = 2,
ACCESS_TYPE_RW = 3,
ACCESS_TYPE_LAST = 4
} aclAccessType_0_8;
#endif // _ACL_ENUMS_0_8_H_
@@ -0,0 +1,182 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_FUNCTORS_0_8_H_
#define _ACL_FUNCTORS_0_8_H_
//! Callback for the log function function pointer that many
// API calls take to have the calling application receive
// information on what errors occur.
typedef void (*aclLogFunction_0_8)(const char *msg, size_t size);
typedef acl_error
(ACL_API_ENTRY *InsertSec_0_8)(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *InsertSym_0_8)(aclCompiler *cl,
aclBinary *binary,
const void *data,
size_t data_size,
aclSections id,
const char *symbol) ACL_API_0_8;
typedef const void *
(ACL_API_ENTRY *ExtractSec_0_8)(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
acl_error *error_code) ACL_API_0_8;
typedef const void *
(ACL_API_ENTRY *ExtractSym_0_8)(aclCompiler *cl,
const aclBinary *binary,
size_t *size,
aclSections id,
const char *symbol,
acl_error *error_code) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *RemoveSec_0_8)(aclCompiler *cl,
aclBinary *binary,
aclSections id) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *RemoveSym_0_8)(aclCompiler *cl,
aclBinary *binary,
aclSections id,
const char *symbol) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *QueryInfo_0_8)(aclCompiler *cl,
const aclBinary *binary,
aclQueryType query,
const char *kernel,
void *data_ptr,
size_t *ptr_size) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *AddDbgArg_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
const char *name,
bool byVal) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *RemoveDbgArg_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
const char *name) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *Compile_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *options,
aclType from,
aclType to,
aclLogFunction_0_8 compile_callback) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *Link_0_8)(aclCompiler *cl,
aclBinary *src_bin,
unsigned int num_libs,
aclBinary **libs,
aclType link_mode,
const char *options,
aclLogFunction_0_8 link_callback) ACL_API_0_8;
typedef const char *
(ACL_API_ENTRY *CompLog_0_8)(aclCompiler *cl) ACL_API_0_8;
typedef const void *
(ACL_API_ENTRY *RetrieveType_0_8)(aclCompiler *cl,
const aclBinary *bin,
const char *name,
size_t *data_size,
aclType type,
acl_error *error_code) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *SetType_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type,
const void *data,
size_t size) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *ConvertType_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *name,
aclType type) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *Disassemble_0_8)(aclCompiler *cl,
aclBinary *bin,
const char *kernel,
aclLogFunction_0_8 disasm_callback) ACL_API_0_8;
typedef const void *
(ACL_API_ENTRY *GetDevBinary_0_8)(aclCompiler *cl,
const aclBinary *bin,
const char *kernel,
size_t *size,
acl_error *error_code) ACL_API_0_8;
typedef aclLoaderData *
(ACL_API_ENTRY *LoaderInit_0_8)(aclCompiler *cl,
aclBinary *bin,
aclLogFunction_0_8 callback,
acl_error *error);
typedef acl_error
(ACL_API_ENTRY *LoaderFini_0_8)(aclLoaderData *data);
typedef aclModule *
(ACL_API_ENTRY *FEToIR_0_8)(aclLoaderData *ald,
const char *source,
size_t data_size,
aclContext *ctx,
acl_error *error) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *SourceToISA_0_8)(aclLoaderData *ald,
const char *source,
size_t data_size) ACL_API_0_8;
typedef aclModule *
(ACL_API_ENTRY *IRPhase_0_8)(aclLoaderData *data,
aclModule *ir,
aclContext *ctx,
acl_error *error) ACL_API_0_8;
typedef aclModule *
(ACL_API_ENTRY *LinkPhase_0_8)(aclLoaderData *data,
aclModule *ir,
unsigned int num_libs,
aclModule **libs,
aclContext *ctx,
acl_error *error) ACL_API_0_8;
typedef const void *
(ACL_API_ENTRY *CGPhase_0_8)(aclLoaderData *data,
aclModule *ir,
aclContext *ctx,
acl_error *error) ACL_API_0_8;
typedef acl_error
(ACL_API_ENTRY *DisasmISA_0_8)(aclLoaderData *data,
const char *kernel,
const void *isa_code,
size_t isa_size) ACL_API_0_8;
typedef void*
(*AllocFunc_0_8)(size_t size) ACL_API_0_8;
typedef void
(*FreeFunc_0_8)(void *ptr) ACL_API_0_8;
#endif // _ACL_FUNCTORS_0_8_H_
@@ -0,0 +1,305 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_STRUCTS_0_8_H_
#define _ACL_STRUCTS_0_8_H_
#define ACL_STRUCT_HEADER \
size_t struct_size
//! A structure that holds information on the various types of arguments
// The format in memory of this structure is
// -------------
// | aclArgData |
// -------------
// |->argStr |
// -------------
// |->typeStr |
// -------------
typedef struct _acl_md_arg_type_0_8 {
ACL_STRUCT_HEADER;
size_t argNameSize;
size_t typeStrSize;
const char *argStr;
const char *typeStr;
union {
struct { // Struct for sampler arguments
unsigned ID;
unsigned isKernelDefined;
unsigned value;
} sampler;
struct { // Struct for image arguments
unsigned resID;
unsigned cbNum;
unsigned cbOffset;
aclAccessType type;
bool is2D;
bool is1D;
bool isArray;
bool isBuffer;
} image;
struct { // struct for atomic counter arguments
unsigned is32bit;
unsigned resID;
unsigned cbNum;
unsigned cbOffset;
} counter;
struct { // struct for semaphore arguments
unsigned resID;
unsigned cbNum;
unsigned cbOffset;
} sema;
struct { // struct for pass by value arguments
unsigned numElements;
unsigned cbNum;
unsigned cbOffset;
aclArgDataType data;
} value;
struct { // struct for pass by pointer arguments
unsigned numElements;
unsigned cbNum;
unsigned cbOffset;
unsigned bufNum;
unsigned align;
aclArgDataType data;
aclMemoryType memory;
aclAccessType type;
bool isVolatile;
bool isRestrict;
bool isPipe;
} pointer;
} arg;
aclArgType type;
bool isConst;
} aclArgData_0_8;
//! A structure that holds information for printf
// The format in memory of this structure is
// --------------
// | aclPrintfFmt|
// --------------
// |->argSizes |
// --------------
// |->fmrStr |
// --------------
typedef struct _acl_md_printf_fmt_0_8 {
ACL_STRUCT_HEADER;
unsigned ID;
size_t numSizes;
size_t fmtStrSize;
uint32_t *argSizes;
const char *fmtStr;
} aclPrintfFmt_0_8;
//! A structure that holds the metadata in the RODATA section.
typedef struct _acl_metadata_0_8 {
ACL_STRUCT_HEADER; // This holds the size of the structure itself for versioning.
size_t data_size; // This holds the size of all the memory allocated for this structure.
uint32_t major, minor, revision, gpuCaps, funcID;
uint32_t gpuRes[5];
size_t wgs[3];
uint32_t wrs[3];
size_t kernelNameSize;
size_t deviceNameSize;
size_t mem[6];
size_t numArgs;
size_t numPrintf;
aclArgData_0_8 *args;
aclPrintfFmt_0_8 *printf;
const char *kernelName;
const char *deviceName;
bool enqueue_kernel;
uint32_t kernel_index;
} aclMetadata_0_8;
//! An structure that holds information on the capabilities of the bif device.
typedef struct _acl_device_caps_rec_0_8 {
ACL_STRUCT_HEADER;
uint32_t flags[4];
uint32_t encryptCode;
} aclDevCaps_0_8;
//! Structure that holds information on the target that the source is
// being compiled for.
typedef struct _acl_target_info_rec_0_8 {
ACL_STRUCT_HEADER;
aclDevType arch_id; // An identifier for the architecture.
uint32_t chip_id; // A identifier for the chip.
} aclTargetInfo_0_8;
// Structure for the version 0.8 of the structure.
typedef struct _acl_binary_opts_rec_0_8 {
ACL_STRUCT_HEADER;
uint32_t elfclass;
uint32_t bitness;
const char *temp_file;
uint32_t kernelArgAlign;
} aclBinaryOptions_0_8;
// Structure for the version 0.8.1 of the structure.
// This versions addes in alloc/dealloc functions.
typedef struct _acl_binary_opts_rec_0_8_1 {
ACL_STRUCT_HEADER;
uint32_t elfclass;
uint32_t bitness;
const char *temp_file;
uint32_t kernelArgAlign;
AllocFunc_0_8 alloc;
FreeFunc_0_8 dealloc;
} aclBinaryOptions_0_8_1;
//! Structure that holds the OpenCL binary information.
typedef struct _acl_bif_rec_0_8 {
ACL_STRUCT_HEADER;
aclTargetInfo_0_8 target; // Information about the target device.
aclBIF* bin; // Pointer to the acl.
aclOptions* options; // Pointer to acl options.
aclBinaryOptions_0_8 binOpts; // Pointer to the binary options.
aclDevCaps_0_8 caps; // Capabilities of the BIF.
} aclBinary_0_8;
//! Version of the aclBinary that uses the 0_8_1 version of the aclBinaryOptions.
typedef struct _acl_bif_rec_0_8_1 {
ACL_STRUCT_HEADER;
aclTargetInfo_0_8 target; // Information about the target device.
aclBIF* bin; // Pointer to the acl.
aclOptions* options; // Pointer to acl options.
aclBinaryOptions_0_8_1 binOpts; // Pointer to the binary options.
aclDevCaps_0_8 caps; // Capabilities of the BIF.
} aclBinary_0_8_1;
#define ACL_LOADER_COMMON\
ACL_STRUCT_HEADER; \
bool isBuiltin; \
const char *libName; \
void *handle; \
LoaderInit init; \
LoaderFini fini;
// Struct that maps to the common structure between all loaders.
typedef struct _acl_common_loader_rec_0_8 {
ACL_LOADER_COMMON;
} aclCommonLoader_0_8;
typedef struct _acl_cl_loader_rec_0_8 {
ACL_LOADER_COMMON;
Compile compile;
Link link;
CompLog getLog;
RetrieveType_0_8 retrieveType;
SetType_0_8 setType;
ConvertType_0_8 convertType;
Disassemble disassemble;
GetDevBinary_0_8 devBinary;
InsertSec insSec;
ExtractSec extSec;
RemoveSec remSec;
InsertSym insSym;
ExtractSym extSym;
RemoveSym remSym;
QueryInfo getInfo;
AddDbgArg addDbg;
RemoveDbgArg removeDbg;
} aclCLLoader_0_8;
//! Structure that holds the required functions
// that sc exports for the SCDLL infrastructure.
typedef struct _acl_sc_loader_rec_0_8 {
ACL_LOADER_COMMON;
uint32_t /*SC_UINT32*/ sc_interface_version;
void /**SC_EXPORT_FUNCTIONS**/ *scef;
// Any version specific fields go here.
} aclSCLoader_0_8;
typedef struct _acl_fe_loader_rec_0_8 {
ACL_LOADER_COMMON;
FEToIR toIR; // Used for Source to aclModule containing LLVMIR
FEToIR toModule; // Used to convert raw SPIR/LLVM-IR to aclModule
SourceToISA toISA; // Used for Source to ISA
} aclFELoader_0_8;
typedef struct _acl_opt_loader_rec_0_8 {
ACL_LOADER_COMMON;
IRPhase optimize; // Used for IR to IR transformation
} aclOptLoader_0_8;
typedef struct _acl_link_loader_rec_0_8 {
ACL_LOADER_COMMON;
LinkPhase link; // Used for Linking in IR modules
IRPhase toLLVMIR; // Used for converting SPIR to LLVMIR
IRPhase toSPIR; // Used for converting LLVMIR to SPIR
} aclLinkLoader_0_8;
typedef struct _acl_cg_loader_rec_0_8 {
ACL_LOADER_COMMON;
CGPhase codegen; // Used for converting from LLVMIR to target ASM.
} aclCGLoader_0_8;
typedef struct _acl_be_loader_rec_0_8 {
ACL_LOADER_COMMON;
SourceToISA finalize; // Used for converting from target source to target ISA.
SourceToISA assemble; // Used for converting from target text to target binary.
DisasmISA disassemble; // Used for converting from target binary to target ISA.
} aclBELoader_0_8;
typedef struct _acl_compiler_opts_rec_0_8 {
ACL_STRUCT_HEADER; // Size of the structure for version checking.
const char *clLib;
const char *feLib;
const char *optLib;
const char *linkLib;
const char *cgLib;
const char *beLib;
const char *scLib;
} aclCompilerOptions_0_8;
typedef struct _acl_compiler_opts_rec_0_8_1 {
ACL_STRUCT_HEADER; // Size of the structure for version checking.
const char* clLib;
const char *feLib;
const char *optLib;
const char *linkLib;
const char *cgLib;
const char *beLib;
const char *scLib;
AllocFunc alloc;
FreeFunc dealloc;
} aclCompilerOptions_0_8_1;
//! Structure that holds the OpenCL compiler and various loaders.
typedef struct _acl_compiler_rec_0_8 {
ACL_STRUCT_HEADER; // Size of structure for version checking.
aclCLLoader clAPI; // Pointer to the compiler API.
aclFELoader feAPI; // Pointer to the FE Loader API.
aclOptLoader optAPI; // Pointer to the Opt Loader API.
aclLinkLoader linkAPI; // Pointer to the Link Loader API.
aclCGLoader cgAPI; // Pointer to the CG Loader API.
aclBELoader beAPI; // Pointer to the BE Loader API.
aclSCLoader scAPI; // Pointer to the SC Loader API.
aclCompilerOptions *opts; // The options structure for the compiler.
void *llvm_shutdown; // Pointer to the llvm shutdown object.
char *buildLog; // Pointer to the current build log.
unsigned logSize; // Size of the current build log.
aclLoaderData *apiData; // pointer to data store for the compiler API loader.
} aclCompilerHandle_0_8;
//! Structure that holds the OpenCL compiler and various loaders.
typedef struct _acl_compiler_rec_0_8_1 {
ACL_STRUCT_HEADER;
aclCLLoader clAPI; // Pointer to the compiler API.
aclFELoader feAPI; // Pointer to the FE Loader API.
aclOptLoader optAPI; // Pointer to the Opt Loader API.
aclLinkLoader linkAPI; // Pointer to the Link Loader API.
aclCGLoader cgAPI; // Pointer to the CG Loader API.
aclBELoader beAPI; // Pointer to the BE Loader API.
aclSCLoader scAPI; // Pointer to the SC Loader API.
AllocFunc alloc;
FreeFunc dealloc;
aclCompilerOptions *opts; // The options structure for the compiler.
void *llvm_shutdown; // Pointer to the llvm shutdown object.
char *buildLog; // Pointer to the current build log.
unsigned logSize; // Size of the current build log.
aclLoaderData *apiData; // pointer to data store for the compiler API loader.
} aclCompilerHandle_0_8_1;
#endif // _ACL_STRUCTS_0_8_H_
@@ -0,0 +1,88 @@
//
// Copyright (c) 2012 Advanced Micro Devices, Inc. All rights reserved.
//
#ifndef _ACL_API_TYPES_0_8_H_
#define _ACL_API_TYPES_0_8_H_
#include "aclDefs.h"
#include <stdint.h>
#include <stddef.h>
// Typedefs that always point to the most recent versions of the objects.
typedef struct _acl_md_arg_type_0_8 aclArgData;
typedef struct _acl_md_printf_fmt_0_8 aclPrintfFmt;
typedef struct _acl_metadata_0_8 aclMetadata;
typedef struct _acl_device_caps_rec_0_8 aclDevCaps;
typedef struct _acl_target_info_rec_0_8 aclTargetInfo;
typedef struct _acl_bif_rec_0_8_1 aclBinary;
typedef struct _acl_binary_opts_rec_0_8_1 aclBinaryOptions;
typedef struct _acl_compiler_rec_0_8_1 aclCompiler;
typedef struct _acl_compiler_opts_rec_0_8_1 aclCompilerOptions;
typedef struct _acl_options_0_8* aclOptions; // Opaque pointer to amd::Options
typedef struct _acl_binary_0_8* aclBIF; // Opaque pointer to bifbase
typedef struct _acl_common_loader_rec_0_8 aclCommonLoader;
typedef struct _acl_cl_loader_rec_0_8 aclCLLoader;
typedef struct _acl_sc_loader_rec_0_8 aclSCLoader;
typedef struct _acl_fe_loader_rec_0_8 aclFELoader;
typedef struct _acl_link_loader_rec_0_8 aclLinkLoader;
typedef struct _acl_opt_loader_rec_0_8 aclOptLoader;
typedef struct _acl_cg_loader_rec_0_8 aclCGLoader;
typedef struct _acl_be_loader_rec_0_8 aclBELoader;
typedef struct _acl_llvm_module_0_8* aclModule; // Opaque pointer to llvm::Module
typedef struct _acl_llvm_context_0_8* aclContext; // Opaque pointer to llvm::Context
typedef struct _acl_loader_data_0_8* aclLoaderData; // Opaque pointer to loader data
#include "aclEnums.h"
// Typedefs for enumerations
typedef enum _acl_error_enum_0_8 acl_error;
typedef enum _comp_device_caps_enum_0_8 compDeviceCaps;
typedef enum _comp_opt_settings_enum_0_8 compOptSettings;
typedef enum _acl_dev_type_enum_0_8 aclDevType;
typedef enum _acl_cl_version_enum_0_8 aclCLVersion;
typedef enum _acl_type_enum_0_8 aclType;
typedef enum _rt_query_types_enum_0_8 aclQueryType;
typedef enum _rt_gpu_caps_enum_0_8 aclGPUCaps;
typedef enum _rt_gpu_resource_enum_0_8 aclGPUResource;
typedef enum _rt_gpu_mem_sizes_enum_0_8 aclGPUMemSizes;
typedef enum _acl_arg_type_enum_0_8 aclArgType;
typedef enum _acl_data_type_enum_0_8 aclArgDataType;
typedef enum _acl_memory_type_enum_0_8 aclMemoryType;
typedef enum _acl_access_type_enum_0_8 aclAccessType;
typedef enum _bif_version_enum_0_8 aclBIFVersion;
typedef enum _bif_platform_enum_0_8 aclPlatform;
typedef enum _bif_sections_enum_0_8 aclSections;
typedef enum _acl_loader_type_enum_0_8 aclLoaderType;
#include "aclFunctors.h"
// Typedefs for function pointers
typedef aclLogFunction_0_8 aclLogFunction;
typedef InsertSec_0_8 InsertSec;
typedef RemoveSec_0_8 RemoveSec;
typedef ExtractSec_0_8 ExtractSec;
typedef InsertSym_0_8 InsertSym;
typedef RemoveSym_0_8 RemoveSym;
typedef ExtractSym_0_8 ExtractSym;
typedef QueryInfo_0_8 QueryInfo;
typedef Compile_0_8 Compile;
typedef Link_0_8 Link;
typedef AddDbgArg_0_8 AddDbgArg;
typedef RemoveDbgArg_0_8 RemoveDbgArg;
typedef CompLog_0_8 CompLog;
typedef RetrieveType_0_8 RetrieveType;
typedef SetType_0_8 SetType;
typedef ConvertType_0_8 ConvertType;
typedef Disassemble_0_8 Disassemble;
typedef GetDevBinary_0_8 GetDevBinary;
typedef LoaderInit_0_8 LoaderInit;
typedef LoaderFini_0_8 LoaderFini;
typedef FEToIR_0_8 FEToIR;
typedef SourceToISA_0_8 SourceToISA;
typedef IRPhase_0_8 IRPhase;
typedef LinkPhase_0_8 LinkPhase;
typedef CGPhase_0_8 CGPhase;
typedef DisasmISA_0_8 DisasmISA;
typedef AllocFunc_0_8 AllocFunc;
typedef FreeFunc_0_8 FreeFunc;
#include "aclStructs.h"
#endif // _CL_API_TYPES_0_8_H_
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,399 @@
//
// 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"
#include "cal.h" // using CALtargetEnum
#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_AMDIL
#define EM_AMDIL 0x4154
#endif
#ifndef EM_ATI_CALIMAGE_BINARY
#define EM_ATI_CALIMAGE_BINARY 125
#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.
// All CAL targets are within [CAL_FIRST, CAL_LAST].
CAL_FIRST = CAL_TARGET_600 + CAL_BASE,
CAL_LAST = CAL_TARGET_LAST + CAL_BASE,
// 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,
LAST_PLATFORM = 3
} 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,
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;
// Is the _fname temporary ?
bool _isTempFile;
// 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; }
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,302 @@
//
// Copyright (c) 2010 Advanced Micro Devices, Inc. All rights reserved.
//
#include "elf_utils.hpp"
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#if defined(__GNUC__)
#include <unistd.h>
#else
#include <io.h>
#endif
/*
See elf_utils.hpp for descriptions about each functions
*/
namespace amd {
#if defined(_MSC_VER)
#define ELF_OPEN _open
#define ELF_READ(f, b, l) _read((f), (b), (unsigned int)(l))
#define ELF_WRITE _write
#define ELF_CLOSE _close
#define ELF_LSEEK _lseek
#else
#define ELF_OPEN open
#define ELF_READ(f, b, l) read((f), (b), (size_t)(l))
#define ELF_WRITE write
#define ELF_CLOSE close
#define ELF_LSEEK lseek
#endif
/*
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 < 0) {
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,145 @@
//
// 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,542 @@
/*-
* 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,7 @@
#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,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,217 @@
/*-
* 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 <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,56 @@
/*-
* 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,218 @@
/*-
* 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
@@ -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,337 @@
/*-
* 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 *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 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,251 @@
/*-
* 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 we aren't a read/write from a file or a read only elf,
// make sure that the headers are loaded. If we are a read/write
// from a file, we should have the headers loaded already.
if ((e->e_cmd == ELF_C_READ
|| (e->e_cmd == ELF_C_RDWR && e->e_fd == -1)) &&
(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_READ
|| (e->e_cmd == ELF_C_RDWR && e->e_fd == -1)) &&
(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,134 @@
/*-
* Copyright (c) 2006,2008 Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <assert.h>
#include <gelf.h>
#include "_libelf.h"
#ifdef ANDROID
#include "roundup.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);
}
File diff suppressed because it is too large Load Diff
@@ -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,130 @@
/*-
* Copyright (c) 2006,2008 Joseph Koshy
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <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,265 @@
/*-
* 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/param.h>
#include <sys/queue.h>
#include <elfdefinitions.h>
#ifdef ANDROID
#include "sys/types.h"
#endif
#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,229 @@
/*-
* 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,461 @@
/*-
* 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);
}

Some files were not shown because too many files have changed in this diff Show More