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 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
Viittaa uudesa ongelmassa
Block a user