A little library for patching symbols at runtime.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5296 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -0,0 +1,162 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfSymbolPatcher.h
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Interface declaration of classes used for patching ELF
|
||||||
|
// symbols. Central class is ElfSymbolPatcher. It is a kind of
|
||||||
|
// roster, managing all necessary infos (loaded images) and
|
||||||
|
// being able to fill ElfSymbolPatchInfos with life.
|
||||||
|
// An ElfSymbolPatchInfo represents a symbol and is able to
|
||||||
|
// patch/restore it. An ElfSymbolPatchGroup bundles several
|
||||||
|
// ElfSymbolPatchInfos and can update their data, e.g.
|
||||||
|
// when images are loaded/unloaded. It uses a
|
||||||
|
// ElfSymbolPatcher internally and provides a more convenient
|
||||||
|
// API for the user.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ELF_SYMBOL_PATCHER_H
|
||||||
|
#define ELF_SYMBOL_PATCHER_H
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
class ElfImage;
|
||||||
|
class ElfSymbolPatcher;
|
||||||
|
class ElfSymbolPatchGroup;
|
||||||
|
|
||||||
|
// ElfSymbolPatchInfo
|
||||||
|
class ElfSymbolPatchInfo {
|
||||||
|
public:
|
||||||
|
ElfSymbolPatchInfo();
|
||||||
|
~ElfSymbolPatchInfo();
|
||||||
|
|
||||||
|
status_t InitCheck() const;
|
||||||
|
|
||||||
|
const char* GetSymbolName() const;
|
||||||
|
void* GetOriginalAddress() const;
|
||||||
|
image_id GetOriginalAddressImage() const;
|
||||||
|
|
||||||
|
status_t Patch(void* newAddress);
|
||||||
|
status_t Restore();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class Entry;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Unset();
|
||||||
|
status_t SetSymbolName(const char* name);
|
||||||
|
void SetOriginalAddress(void* address,
|
||||||
|
image_id image);
|
||||||
|
status_t CreateEntry(image_id image, BList* targets);
|
||||||
|
bool DeleteEntry(image_id image);
|
||||||
|
Entry* EntryAt(int32 index);
|
||||||
|
Entry* EntryFor(image_id image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ElfSymbolPatcher;
|
||||||
|
friend class ElfSymbolPatchGroup;
|
||||||
|
|
||||||
|
BString fSymbolName;
|
||||||
|
void* fOriginalAddress;
|
||||||
|
image_id fOriginalAddressImage;
|
||||||
|
BList fEntries;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ElfSymbolPatcher
|
||||||
|
class ElfSymbolPatcher {
|
||||||
|
public:
|
||||||
|
class UpdateAdapter;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ElfSymbolPatcher();
|
||||||
|
~ElfSymbolPatcher();
|
||||||
|
|
||||||
|
status_t InitCheck() const;
|
||||||
|
status_t Update(UpdateAdapter* updateAdapter = NULL);
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
status_t GetSymbolPatchInfo(const char* symbolName,
|
||||||
|
ElfSymbolPatchInfo* info);
|
||||||
|
status_t UpdateSymbolPatchInfo(ElfSymbolPatchInfo* info,
|
||||||
|
ElfImage* image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _Init();
|
||||||
|
void _Cleanup();
|
||||||
|
|
||||||
|
ElfImage* _ImageAt(int32 index) const;
|
||||||
|
ElfImage* _ImageForID(image_id id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
BList fImages;
|
||||||
|
status_t fInitStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
// UpdateAdapter
|
||||||
|
class ElfSymbolPatcher::UpdateAdapter {
|
||||||
|
public:
|
||||||
|
UpdateAdapter();
|
||||||
|
virtual ~UpdateAdapter();
|
||||||
|
|
||||||
|
virtual void ImageAdded(ElfImage* image);
|
||||||
|
virtual void ImageRemoved(ElfImage* image);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ElfSymbolPatchGroup
|
||||||
|
class ElfSymbolPatchGroup : private ElfSymbolPatcher::UpdateAdapter {
|
||||||
|
public:
|
||||||
|
ElfSymbolPatchGroup(
|
||||||
|
ElfSymbolPatcher* patcher = NULL);
|
||||||
|
~ElfSymbolPatchGroup();
|
||||||
|
|
||||||
|
ElfSymbolPatcher* GetPatcher() const { return fPatcher; }
|
||||||
|
|
||||||
|
status_t AddPatch(const char* symbolName,
|
||||||
|
void* newAddress,
|
||||||
|
void** originalAddress);
|
||||||
|
|
||||||
|
void RemoveAllPatches();
|
||||||
|
|
||||||
|
status_t Patch();
|
||||||
|
status_t Restore();
|
||||||
|
|
||||||
|
status_t Update();
|
||||||
|
|
||||||
|
private:
|
||||||
|
class PatchInfo : public ElfSymbolPatchInfo {
|
||||||
|
public:
|
||||||
|
void* fNewAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void ImageAdded(ElfImage* image);
|
||||||
|
virtual void ImageRemoved(ElfImage* image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfSymbolPatcher* fPatcher;
|
||||||
|
BList fPatchInfos;
|
||||||
|
bool fOwnsPatcher;
|
||||||
|
bool fPatched;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ELF_SYMBOL_PATCHER_H
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
// Elf.h
|
||||||
|
|
||||||
|
#ifndef _ELF_H
|
||||||
|
#define _ELF_H
|
||||||
|
|
||||||
|
// types
|
||||||
|
typedef uint32 Elf32_Addr;
|
||||||
|
typedef uint16 Elf32_Half;
|
||||||
|
typedef uint32 Elf32_Off;
|
||||||
|
typedef int32 Elf32_Sword;
|
||||||
|
typedef uint32 Elf32_Word;
|
||||||
|
|
||||||
|
// e_ident indices
|
||||||
|
#define EI_MAG0 0
|
||||||
|
#define EI_MAG1 1
|
||||||
|
#define EI_MAG2 2
|
||||||
|
#define EI_MAG3 3
|
||||||
|
#define EI_CLASS 4
|
||||||
|
#define EI_DATA 5
|
||||||
|
#define EI_VERSION 6
|
||||||
|
#define EI_PAD 7
|
||||||
|
#define EI_NIDENT 16
|
||||||
|
|
||||||
|
// ELF magic
|
||||||
|
#define ELFMAG0 0x7f
|
||||||
|
#define ELFMAG1 'E'
|
||||||
|
#define ELFMAG2 'L'
|
||||||
|
#define ELFMAG3 'F'
|
||||||
|
|
||||||
|
// class
|
||||||
|
#define ELFCLASSNONE 0
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
|
||||||
|
// version
|
||||||
|
#define EV_NONE 0
|
||||||
|
#define EV_CURRENT 1
|
||||||
|
|
||||||
|
// object file header
|
||||||
|
typedef struct {
|
||||||
|
unsigned char e_ident[EI_NIDENT];
|
||||||
|
Elf32_Half e_type;
|
||||||
|
Elf32_Half e_machine;
|
||||||
|
Elf32_Word e_version;
|
||||||
|
Elf32_Addr e_entry;
|
||||||
|
Elf32_Off e_phoff;
|
||||||
|
Elf32_Off e_shoff;
|
||||||
|
Elf32_Word e_flags;
|
||||||
|
Elf32_Half e_ehsize;
|
||||||
|
Elf32_Half e_phentsize;
|
||||||
|
Elf32_Half e_phnum;
|
||||||
|
Elf32_Half e_shentsize;
|
||||||
|
Elf32_Half e_shnum;
|
||||||
|
Elf32_Half e_shstrndx;
|
||||||
|
} Elf32_Ehdr;
|
||||||
|
|
||||||
|
// e_ident EI_CLASS and EI_DATA values
|
||||||
|
#define ELFCLASSNONE 0
|
||||||
|
#define ELFCLASS32 1
|
||||||
|
#define ELFCLASS64 2
|
||||||
|
#define ELFDATANONE 0
|
||||||
|
#define ELFDATA2LSB 1
|
||||||
|
#define ELFDATA2MSB 2
|
||||||
|
|
||||||
|
// special section header indices
|
||||||
|
#define SHN_UNDEF 0
|
||||||
|
#define SHN_LORESERVE 0xff00
|
||||||
|
#define SHN_LOPROC 0xff00
|
||||||
|
#define SHN_HIPROC 0xff1f
|
||||||
|
#define SHN_ABS 0xfff1
|
||||||
|
#define SHN_COMMON 0xfff2
|
||||||
|
#define SHN_HIRESERVE 0xffff
|
||||||
|
|
||||||
|
// program header
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Word p_type;
|
||||||
|
Elf32_Off p_offset;
|
||||||
|
Elf32_Addr p_vaddr;
|
||||||
|
Elf32_Addr p_paddr;
|
||||||
|
Elf32_Word p_filesz;
|
||||||
|
Elf32_Word p_memsz;
|
||||||
|
Elf32_Word p_flags;
|
||||||
|
Elf32_Word p_align;
|
||||||
|
} Elf32_Phdr;
|
||||||
|
|
||||||
|
// p_type
|
||||||
|
#define PT_NULL 0
|
||||||
|
#define PT_LOAD 1
|
||||||
|
#define PT_DYNAMIC 2
|
||||||
|
#define PT_INTERP 3
|
||||||
|
#define PT_NOTE 4
|
||||||
|
#define PT_SHLIB 5
|
||||||
|
#define PT_PHDIR 6
|
||||||
|
#define PT_LOPROC 0x70000000
|
||||||
|
#define PT_HIPROC 0x7fffffff
|
||||||
|
|
||||||
|
// section header
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Word sh_name;
|
||||||
|
Elf32_Word sh_type;
|
||||||
|
Elf32_Word sh_flags;
|
||||||
|
Elf32_Addr sh_addr;
|
||||||
|
Elf32_Off sh_offset;
|
||||||
|
Elf32_Word sh_size;
|
||||||
|
Elf32_Word sh_link;
|
||||||
|
Elf32_Word sh_info;
|
||||||
|
Elf32_Word sh_addralign;
|
||||||
|
Elf32_Word sh_entsize;
|
||||||
|
} Elf32_Shdr;
|
||||||
|
|
||||||
|
// sh_type values
|
||||||
|
#define SHT_NULL 0
|
||||||
|
#define SHT_PROGBITS 1
|
||||||
|
#define SHT_SYMTAB 2
|
||||||
|
#define SHT_STRTAB 3
|
||||||
|
#define SHT_RELA 4
|
||||||
|
#define SHT_HASH 5
|
||||||
|
#define SHT_DYNAMIC 6
|
||||||
|
#define SHT_NOTE 7
|
||||||
|
#define SHT_NOBITS 8
|
||||||
|
#define SHT_REL 9
|
||||||
|
#define SHT_SHLIB 10
|
||||||
|
#define SHT_DYNSYM 11
|
||||||
|
#define SHT_LOPROC 0x70000000
|
||||||
|
#define SHT_HIPROC 0x7fffffff
|
||||||
|
#define SHT_LOUSER 0x80000000
|
||||||
|
#define SHT_HIUSER 0xffffffff
|
||||||
|
|
||||||
|
// relocation entry
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Addr r_offset;
|
||||||
|
Elf32_Word r_info;
|
||||||
|
} Elf32_Rel;
|
||||||
|
|
||||||
|
// relocation entry with addend
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Addr r_offset;
|
||||||
|
Elf32_Word r_info;
|
||||||
|
Elf32_Sword r_addend;
|
||||||
|
} Elf32_Rela;
|
||||||
|
|
||||||
|
// r_info accessors
|
||||||
|
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||||
|
#define ELF32_R_TYPE(i) ((unsigned char)(i))
|
||||||
|
#define ELF32_R_INFO(s, t) ((s) << 8 + (unsigned char)(t))
|
||||||
|
|
||||||
|
// relocation types (i368 specific)
|
||||||
|
#define R_386_NONE 0
|
||||||
|
#define R_386_32 1
|
||||||
|
#define R_386_PC32 2
|
||||||
|
#define R_386_GOT32 3
|
||||||
|
#define R_386_PLT32 4
|
||||||
|
#define R_386_COPY 5
|
||||||
|
#define R_386_GLOB_DAT 6
|
||||||
|
#define R_386_JMP_SLOT 7
|
||||||
|
#define R_386_RELATIVE 8
|
||||||
|
#define R_386_GOTOFF 9
|
||||||
|
#define R_386_GOTPC 10
|
||||||
|
|
||||||
|
// symbol table entry
|
||||||
|
typedef struct {
|
||||||
|
Elf32_Word st_name;
|
||||||
|
Elf32_Addr st_value;
|
||||||
|
Elf32_Word st_size;
|
||||||
|
Elf32_Word st_info;
|
||||||
|
Elf32_Word st_other;
|
||||||
|
Elf32_Word st_shndx;
|
||||||
|
} Elf32_Sym;
|
||||||
|
|
||||||
|
// st_info accessors
|
||||||
|
#define ELF32_ST_BIND(i) ((i) >> 4)
|
||||||
|
#define ELF32_ST_TYPE(i) ((i) & 0xf)
|
||||||
|
#define ELF32_ST_INFO(b, t) ((b) << 4 + (t) & 0xf)
|
||||||
|
|
||||||
|
// symbol binding
|
||||||
|
#define STB_LOCAL 0
|
||||||
|
#define STB_GLOBAL 1
|
||||||
|
#define STB_WEAK 2
|
||||||
|
#define STB_LOPROC 13
|
||||||
|
#define STB_HIPROC 15
|
||||||
|
|
||||||
|
// symbol types
|
||||||
|
#define STT_NOTYPE 0
|
||||||
|
#define STT_OBJECT 1
|
||||||
|
#define STT_FUNC 2
|
||||||
|
#define STT_SECTION 3
|
||||||
|
#define STT_FILE 4
|
||||||
|
#define STT_LOPROC 13
|
||||||
|
#define STT_HIPROC 15
|
||||||
|
|
||||||
|
|
||||||
|
#endif // _ELF_H
|
||||||
@@ -0,0 +1,716 @@
|
|||||||
|
// ElfFile.cpp
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfFile.cpp
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Implementation of classes for accessing ELF file,
|
||||||
|
// or more precisely for iterating through their relocation
|
||||||
|
// sections.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ElfFile.h"
|
||||||
|
|
||||||
|
// sanity bounds
|
||||||
|
static const uint32 kMaxELFHeaderSize = sizeof(Elf32_Ehdr) + 32;
|
||||||
|
|
||||||
|
// read_exactly
|
||||||
|
static
|
||||||
|
status_t
|
||||||
|
read_exactly(BPositionIO &file, off_t position, void *buffer, size_t size,
|
||||||
|
const char *errorMessage = NULL)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
ssize_t read = file.ReadAt(position, buffer, size);
|
||||||
|
if (read < 0)
|
||||||
|
error = read;
|
||||||
|
else if ((size_t)read != size)
|
||||||
|
error = B_ERROR;
|
||||||
|
if (error != B_OK && errorMessage)
|
||||||
|
puts(errorMessage);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ElfSection
|
||||||
|
|
||||||
|
class ElfSection {
|
||||||
|
public:
|
||||||
|
ElfSection();
|
||||||
|
~ElfSection();
|
||||||
|
|
||||||
|
void SetTo(ElfFile* file, Elf32_Shdr* header);
|
||||||
|
void Unset();
|
||||||
|
bool IsInitialized() const { return fHeader; }
|
||||||
|
|
||||||
|
ElfFile* GetFile() const;
|
||||||
|
Elf32_Shdr* GetHeader() const { return fHeader; }
|
||||||
|
const char* GetName() const;
|
||||||
|
uint8* GetData() const { return fData; }
|
||||||
|
size_t GetSize() const;
|
||||||
|
Elf32_Word GetType() const;
|
||||||
|
Elf32_Word GetLink() const;
|
||||||
|
Elf32_Word GetInfo() const;
|
||||||
|
size_t GetEntrySize() const;
|
||||||
|
int32 CountEntries() const;
|
||||||
|
|
||||||
|
status_t Load();
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
void Dump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfFile* fFile;
|
||||||
|
Elf32_Shdr* fHeader;
|
||||||
|
uint8* fData;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSection::ElfSection()
|
||||||
|
: fFile(NULL),
|
||||||
|
fHeader(NULL),
|
||||||
|
fData(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSection::~ElfSection()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
void
|
||||||
|
ElfSection::SetTo(ElfFile* file, Elf32_Shdr* header)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
fFile = file;
|
||||||
|
fHeader = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfSection::Unset()
|
||||||
|
{
|
||||||
|
Unload();
|
||||||
|
fFile = NULL;
|
||||||
|
fHeader = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetFile
|
||||||
|
ElfFile*
|
||||||
|
ElfSection::GetFile() const
|
||||||
|
{
|
||||||
|
return fFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName
|
||||||
|
const char*
|
||||||
|
ElfSection::GetName() const
|
||||||
|
{
|
||||||
|
const char* name = NULL;
|
||||||
|
if (fHeader && fFile) {
|
||||||
|
size_t size = 0;
|
||||||
|
const char* nameSection = fFile->GetSectionHeaderStrings(&size);
|
||||||
|
if (nameSection && fHeader->sh_name < size)
|
||||||
|
name = nameSection + fHeader->sh_name;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSize
|
||||||
|
size_t
|
||||||
|
ElfSection::GetSize() const
|
||||||
|
{
|
||||||
|
return fHeader->sh_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType
|
||||||
|
Elf32_Word
|
||||||
|
ElfSection::GetType() const
|
||||||
|
{
|
||||||
|
return fHeader->sh_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLink
|
||||||
|
Elf32_Word
|
||||||
|
ElfSection::GetLink() const
|
||||||
|
{
|
||||||
|
return fHeader->sh_link;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetInfo
|
||||||
|
Elf32_Word
|
||||||
|
ElfSection::GetInfo() const
|
||||||
|
{
|
||||||
|
return fHeader->sh_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetEntrySize
|
||||||
|
size_t
|
||||||
|
ElfSection::GetEntrySize() const
|
||||||
|
{
|
||||||
|
return fHeader->sh_entsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CountEntries
|
||||||
|
int32
|
||||||
|
ElfSection::CountEntries() const
|
||||||
|
{
|
||||||
|
int32 count = 0;
|
||||||
|
if (fHeader) {
|
||||||
|
if (GetEntrySize() == 0)
|
||||||
|
return 0;
|
||||||
|
count = GetSize() / GetEntrySize();
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load
|
||||||
|
status_t
|
||||||
|
ElfSection::Load()
|
||||||
|
{
|
||||||
|
status_t error = B_ERROR;
|
||||||
|
if (fHeader && !fData && fHeader->sh_type != SHT_NULL
|
||||||
|
&& fHeader->sh_type != SHT_NOBITS) {
|
||||||
|
BFile* file = fFile->GetFile();
|
||||||
|
// allocate memory
|
||||||
|
fData = new uint8[fHeader->sh_size];
|
||||||
|
if (!fData)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
// read the data
|
||||||
|
error = read_exactly(*file, fHeader->sh_offset, fData,
|
||||||
|
fHeader->sh_size, "Failed to read section!\n");
|
||||||
|
if (error != B_OK)
|
||||||
|
Unload();
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload
|
||||||
|
void
|
||||||
|
ElfSection::Unload()
|
||||||
|
{
|
||||||
|
if (fData) {
|
||||||
|
delete[] fData;
|
||||||
|
fData = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump
|
||||||
|
void
|
||||||
|
ElfSection::Dump()
|
||||||
|
{
|
||||||
|
printf("section %32s: size: %lu\n", GetName(), GetSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ElfSymbol
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbol::ElfSymbol(ElfSection* section, int32 index)
|
||||||
|
: fSection(section),
|
||||||
|
fIndex(index),
|
||||||
|
fSymbol(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbol::~ElfSymbol()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
void
|
||||||
|
ElfSymbol::SetTo(ElfSection* section, int32 index)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
fSection = section;
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfSymbol::Unset()
|
||||||
|
{
|
||||||
|
fSection = NULL;
|
||||||
|
fIndex = -1;
|
||||||
|
fSymbol = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbolStruct
|
||||||
|
const Elf32_Sym*
|
||||||
|
ElfSymbol::GetSymbolStruct()
|
||||||
|
{
|
||||||
|
Elf32_Sym* symbol = fSymbol;
|
||||||
|
if (!symbol && fSection && fSection->GetData()) {
|
||||||
|
size_t symbolSize = fSection->GetEntrySize();
|
||||||
|
if (symbolSize == 0)
|
||||||
|
return NULL;
|
||||||
|
int32 symbolCount = fSection->GetSize() / symbolSize;
|
||||||
|
if (fIndex >= 0 && fIndex < symbolCount)
|
||||||
|
symbol = (Elf32_Sym*)(fSection->GetData() + fIndex * symbolSize);
|
||||||
|
}
|
||||||
|
return symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetName
|
||||||
|
const char*
|
||||||
|
ElfSymbol::GetName()
|
||||||
|
{
|
||||||
|
const char* name = NULL;
|
||||||
|
if (const Elf32_Sym* symbol = GetSymbolStruct()) {
|
||||||
|
size_t size = 0;
|
||||||
|
const char* data = fSection->GetFile()->GetStringSectionStrings(
|
||||||
|
fSection->GetLink(), &size);
|
||||||
|
if (data && symbol->st_name < size)
|
||||||
|
name = data + symbol->st_name;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBinding
|
||||||
|
uint32
|
||||||
|
ElfSymbol::GetBinding()
|
||||||
|
{
|
||||||
|
uint32 binding = STB_LOCAL;
|
||||||
|
if (const Elf32_Sym* symbol = GetSymbolStruct())
|
||||||
|
binding = ELF32_ST_BIND(symbol->st_info);
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType
|
||||||
|
uint32
|
||||||
|
ElfSymbol::GetType()
|
||||||
|
{
|
||||||
|
uint32 type = STT_NOTYPE;
|
||||||
|
if (const Elf32_Sym* symbol = GetSymbolStruct())
|
||||||
|
type = ELF32_ST_TYPE(symbol->st_info);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetTargetSectionIndex
|
||||||
|
uint32
|
||||||
|
ElfSymbol::GetTargetSectionIndex()
|
||||||
|
{
|
||||||
|
uint32 index = SHN_UNDEF;
|
||||||
|
if (const Elf32_Sym* symbol = GetSymbolStruct())
|
||||||
|
index = symbol->st_shndx;
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ElfRelocation
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfRelocation::ElfRelocation(ElfSection* section, int32 index)
|
||||||
|
: fSection(section),
|
||||||
|
fIndex(index),
|
||||||
|
fRelocation(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfRelocation::~ElfRelocation()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
void
|
||||||
|
ElfRelocation::SetTo(ElfSection* section, int32 index)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
fSection = section;
|
||||||
|
fIndex = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfRelocation::Unset()
|
||||||
|
{
|
||||||
|
fSection = NULL;
|
||||||
|
fIndex = -1;
|
||||||
|
fRelocation = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRelocationStruct
|
||||||
|
Elf32_Rel*
|
||||||
|
ElfRelocation::GetRelocationStruct()
|
||||||
|
{
|
||||||
|
Elf32_Rel* relocation = fRelocation;
|
||||||
|
if (!relocation && fSection) {
|
||||||
|
if (!fSection->GetData()) {
|
||||||
|
if (fSection->Load() != B_OK)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
size_t entrySize = fSection->GetEntrySize();
|
||||||
|
if (entrySize == 0 || entrySize < sizeof(Elf32_Rel))
|
||||||
|
return NULL;
|
||||||
|
int32 entryCount = fSection->GetSize() / entrySize;
|
||||||
|
if (fIndex >= 0 && fIndex < entryCount) {
|
||||||
|
relocation = (Elf32_Rel*)(fSection->GetData()
|
||||||
|
+ fIndex * entrySize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return relocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetType
|
||||||
|
uint32
|
||||||
|
ElfRelocation::GetType()
|
||||||
|
{
|
||||||
|
uint32 type = R_386_NONE;
|
||||||
|
if (Elf32_Rel* relocation = GetRelocationStruct())
|
||||||
|
type = ELF32_R_TYPE(relocation->r_info);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbolIndex
|
||||||
|
uint32
|
||||||
|
ElfRelocation::GetSymbolIndex()
|
||||||
|
{
|
||||||
|
uint32 index = 0;
|
||||||
|
if (Elf32_Rel* relocation = GetRelocationStruct())
|
||||||
|
index = ELF32_R_SYM(relocation->r_info);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOffset
|
||||||
|
Elf32_Addr
|
||||||
|
ElfRelocation::GetOffset()
|
||||||
|
{
|
||||||
|
Elf32_Addr offset = 0;
|
||||||
|
if (Elf32_Rel* relocation = GetRelocationStruct())
|
||||||
|
offset = relocation->r_offset;
|
||||||
|
return offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbol
|
||||||
|
status_t
|
||||||
|
ElfRelocation::GetSymbol(ElfSymbol* symbol)
|
||||||
|
{
|
||||||
|
status_t error = B_BAD_VALUE;
|
||||||
|
if (symbol && fSection) {
|
||||||
|
uint32 index = GetSymbolIndex();
|
||||||
|
if (ElfSection* symbols
|
||||||
|
= fSection->GetFile()->SectionAt(fSection->GetLink(), true)) {
|
||||||
|
symbol->SetTo(symbols, index);
|
||||||
|
if (symbol->GetSymbolStruct())
|
||||||
|
error = B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ElfRelocationIterator
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfRelocationIterator::ElfRelocationIterator(ElfFile* file)
|
||||||
|
: fFile(file),
|
||||||
|
fSectionIndex(-1),
|
||||||
|
fEntryIndex(-1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfRelocationIterator::~ElfRelocationIterator()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetNext
|
||||||
|
bool
|
||||||
|
ElfRelocationIterator::GetNext(ElfRelocation* relocation)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
if (fFile && relocation) {
|
||||||
|
// set to possible entry
|
||||||
|
ElfSection* section = NULL;
|
||||||
|
if (fSectionIndex < 0) {
|
||||||
|
fSectionIndex = 0;
|
||||||
|
fEntryIndex = 0;
|
||||||
|
section = _FindNextSection();
|
||||||
|
} else {
|
||||||
|
fEntryIndex++;
|
||||||
|
section = fFile->SectionAt(fSectionIndex);
|
||||||
|
}
|
||||||
|
// find next valid entry
|
||||||
|
while (section && fEntryIndex >= section->CountEntries()) {
|
||||||
|
fSectionIndex++;
|
||||||
|
section = _FindNextSection();
|
||||||
|
fEntryIndex = 0;
|
||||||
|
}
|
||||||
|
// set result
|
||||||
|
if (section) {
|
||||||
|
relocation->SetTo(section, fEntryIndex);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _FindNextSection
|
||||||
|
ElfSection*
|
||||||
|
ElfRelocationIterator::_FindNextSection()
|
||||||
|
{
|
||||||
|
if (fFile) {
|
||||||
|
for (; fSectionIndex < fFile->CountSections(); fSectionIndex++) {
|
||||||
|
ElfSection* section = fFile->SectionAt(fSectionIndex);
|
||||||
|
if (section && section->GetType() == SHT_REL)
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ElfFile
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfFile::ElfFile()
|
||||||
|
: fFile(),
|
||||||
|
fSectionHeaders(NULL),
|
||||||
|
fSections(NULL),
|
||||||
|
fSectionCount(0),
|
||||||
|
fSectionHeaderSize(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfFile::~ElfFile()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
status_t
|
||||||
|
ElfFile::SetTo(const char *filename)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
status_t error = _SetTo(filename);
|
||||||
|
if (error)
|
||||||
|
Unset();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfFile::Unset()
|
||||||
|
{
|
||||||
|
// delete sections
|
||||||
|
if (fSections) {
|
||||||
|
delete[] fSections;
|
||||||
|
fSections = NULL;
|
||||||
|
}
|
||||||
|
// delete section headers
|
||||||
|
if (fSectionHeaders) {
|
||||||
|
delete[] fSectionHeaders;
|
||||||
|
fSectionHeaders = NULL;
|
||||||
|
}
|
||||||
|
fSectionCount = 0;
|
||||||
|
fSectionHeaderSize = 0;
|
||||||
|
fFile.Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload
|
||||||
|
void
|
||||||
|
ElfFile::Unload()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < fSectionCount; i++)
|
||||||
|
fSections[i].Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSectionHeaderStrings
|
||||||
|
const char*
|
||||||
|
ElfFile::GetSectionHeaderStrings(size_t* size)
|
||||||
|
{
|
||||||
|
return GetStringSectionStrings(fHeader.e_shstrndx, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStringSectionStrings
|
||||||
|
const char*
|
||||||
|
ElfFile::GetStringSectionStrings(int32 index, size_t* _size)
|
||||||
|
{
|
||||||
|
const char* data = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
if (ElfSection* section = SectionAt(index, true)) {
|
||||||
|
data = (const char*)section->GetData();
|
||||||
|
size = (data ? section->GetSize() : 0);
|
||||||
|
}
|
||||||
|
// set results
|
||||||
|
if (_size)
|
||||||
|
*_size = size;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SectionAt
|
||||||
|
ElfSection*
|
||||||
|
ElfFile::SectionAt(int32 index, bool load)
|
||||||
|
{
|
||||||
|
ElfSection* section = NULL;
|
||||||
|
if (fSections && index >= 0 && index < fSectionCount) {
|
||||||
|
section = fSections + index;
|
||||||
|
if (load && !section->GetData()) {
|
||||||
|
if (section->Load() != B_OK) {
|
||||||
|
section = NULL;
|
||||||
|
printf("Failed to load section %ld\n", index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dump
|
||||||
|
void
|
||||||
|
ElfFile::Dump()
|
||||||
|
{
|
||||||
|
printf("%ld sections\n", fSectionCount);
|
||||||
|
for (int i = 0; i < fSectionCount; i++)
|
||||||
|
fSections[i].Dump();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _SetTo
|
||||||
|
status_t
|
||||||
|
ElfFile::_SetTo(const char *filename)
|
||||||
|
{
|
||||||
|
if (!filename)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
// open file
|
||||||
|
status_t error = fFile.SetTo(filename, B_READ_ONLY);
|
||||||
|
// get the file size
|
||||||
|
off_t fileSize = 0;
|
||||||
|
error = fFile.GetSize(&fileSize);
|
||||||
|
if (error != B_OK) {
|
||||||
|
printf("Failed to get file size!\n");
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
// read ELF header
|
||||||
|
error = read_exactly(fFile, 0, &fHeader, sizeof(Elf32_Ehdr),
|
||||||
|
"Failed to read ELF object header!\n");
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
// check the ident field
|
||||||
|
// magic
|
||||||
|
if (fHeader.e_ident[EI_MAG0] != ELFMAG0
|
||||||
|
|| fHeader.e_ident[EI_MAG1] != ELFMAG1
|
||||||
|
|| fHeader.e_ident[EI_MAG2] != ELFMAG2
|
||||||
|
|| fHeader.e_ident[EI_MAG3] != ELFMAG3) {
|
||||||
|
printf("Bad ELF file magic!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// class
|
||||||
|
if (fHeader.e_ident[EI_CLASS] != ELFCLASS32) {
|
||||||
|
printf("Wrong ELF class!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// check data encoding (endianess)
|
||||||
|
if (fHeader.e_ident[EI_DATA] != ELFDATA2LSB) {
|
||||||
|
printf("Wrong data encoding!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// version
|
||||||
|
if (fHeader.e_ident[EI_VERSION] != EV_CURRENT) {
|
||||||
|
printf("Wrong data encoding!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// get the header values
|
||||||
|
uint32 headerSize = fHeader.e_ehsize;
|
||||||
|
uint32 sectionHeaderTableOffset = fHeader.e_shoff;
|
||||||
|
uint32 sectionHeaderSize = fHeader.e_shentsize;
|
||||||
|
uint32 sectionHeaderCount = fHeader.e_shnum;
|
||||||
|
// check the sanity of the header values
|
||||||
|
// ELF header size
|
||||||
|
if (headerSize < sizeof(Elf32_Ehdr) || headerSize > kMaxELFHeaderSize) {
|
||||||
|
printf("Invalid ELF header: invalid ELF header size: %lu.",
|
||||||
|
headerSize);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// section header table offset
|
||||||
|
if (sectionHeaderTableOffset == 0) {
|
||||||
|
printf("ELF file has no section header table!\n");
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
uint32 sectionHeaderTableSize = 0;
|
||||||
|
if (sectionHeaderTableOffset < headerSize
|
||||||
|
|| sectionHeaderTableOffset > fileSize) {
|
||||||
|
printf("Invalid ELF header: invalid section header table offset: %lu.",
|
||||||
|
sectionHeaderTableOffset);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// section header table offset
|
||||||
|
sectionHeaderTableSize = sectionHeaderSize * sectionHeaderCount;
|
||||||
|
if (sectionHeaderSize < sizeof(Elf32_Shdr)
|
||||||
|
|| sectionHeaderTableOffset + sectionHeaderTableSize > fileSize) {
|
||||||
|
printf("Invalid ELF header: section header table exceeds file: %lu.",
|
||||||
|
sectionHeaderTableOffset + sectionHeaderTableSize);
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
// allocate memory for the section header table and read it
|
||||||
|
fSectionHeaders = new(nothrow) uint8[sectionHeaderTableSize];
|
||||||
|
fSectionCount = sectionHeaderCount;
|
||||||
|
fSectionHeaderSize = sectionHeaderSize;
|
||||||
|
if (!fSectionHeaders)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
error = read_exactly(fFile, sectionHeaderTableOffset, fSectionHeaders,
|
||||||
|
sectionHeaderTableSize,
|
||||||
|
"Failed to read section headers!\n");
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
// allocate memory for the section pointers
|
||||||
|
fSections = new(nothrow) ElfSection[fSectionCount];
|
||||||
|
if (!fSections)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
// init the sections
|
||||||
|
for (int i = 0; i < fSectionCount; i++)
|
||||||
|
fSections[i].SetTo(this, _SectionHeaderAt(i));
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _SectionHeaderAt
|
||||||
|
Elf32_Shdr*
|
||||||
|
ElfFile::_SectionHeaderAt(int32 index)
|
||||||
|
{
|
||||||
|
Elf32_Shdr* header = NULL;
|
||||||
|
if (fSectionHeaders && index >= 0 && index < fSectionCount)
|
||||||
|
header = (Elf32_Shdr*)(fSectionHeaders + index * fSectionHeaderSize);
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _LoadSection
|
||||||
|
status_t
|
||||||
|
ElfFile::_LoadSection(int32 index)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
if (fSections && index >= 0 && index < fSectionCount) {
|
||||||
|
ElfSection& section = fSections[index];
|
||||||
|
error = section.Load();
|
||||||
|
} else
|
||||||
|
error = B_BAD_VALUE;
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfFile.h
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Interface declarations of classes for accessing ELF file,
|
||||||
|
// or more precisely for iterating through their relocation
|
||||||
|
// sections.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ELF_FILE_H
|
||||||
|
#define ELF_FILE_H
|
||||||
|
|
||||||
|
#include <File.h>
|
||||||
|
#include <image.h>
|
||||||
|
|
||||||
|
#include "Elf.h"
|
||||||
|
|
||||||
|
class ElfFile;
|
||||||
|
class ElfSection;
|
||||||
|
|
||||||
|
// ElfSymbol
|
||||||
|
class ElfSymbol {
|
||||||
|
public:
|
||||||
|
ElfSymbol(ElfSection* section = NULL,
|
||||||
|
int32 index = -1);
|
||||||
|
~ElfSymbol();
|
||||||
|
|
||||||
|
void SetTo(ElfSection* section, int32 index);
|
||||||
|
void Unset();
|
||||||
|
|
||||||
|
const Elf32_Sym* GetSymbolStruct();
|
||||||
|
const char* GetName();
|
||||||
|
uint32 GetBinding();
|
||||||
|
uint32 GetType();
|
||||||
|
uint32 GetTargetSectionIndex();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfSection* fSection;
|
||||||
|
int32 fIndex;
|
||||||
|
Elf32_Sym* fSymbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ElfRelocation
|
||||||
|
class ElfRelocation {
|
||||||
|
public:
|
||||||
|
ElfRelocation(ElfSection* section = NULL,
|
||||||
|
int32 index = -1);
|
||||||
|
~ElfRelocation();
|
||||||
|
|
||||||
|
void SetTo(ElfSection* section, int32 index);
|
||||||
|
void Unset();
|
||||||
|
|
||||||
|
Elf32_Rel* GetRelocationStruct();
|
||||||
|
uint32 GetType();
|
||||||
|
uint32 GetSymbolIndex();
|
||||||
|
Elf32_Addr GetOffset();
|
||||||
|
status_t GetSymbol(ElfSymbol* symbol);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfSection* fSection;
|
||||||
|
int32 fIndex;
|
||||||
|
Elf32_Rel* fRelocation;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ElfRelocationIterator
|
||||||
|
class ElfRelocationIterator {
|
||||||
|
public:
|
||||||
|
ElfRelocationIterator(ElfFile* file);
|
||||||
|
~ElfRelocationIterator();
|
||||||
|
|
||||||
|
bool GetNext(ElfRelocation* relocation);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfSection* _FindNextSection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ElfFile* fFile;
|
||||||
|
int32 fSectionIndex;
|
||||||
|
int32 fEntryIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ElfFile
|
||||||
|
class ElfFile {
|
||||||
|
public:
|
||||||
|
ElfFile();
|
||||||
|
~ElfFile();
|
||||||
|
status_t SetTo(const char *filename);
|
||||||
|
void Unset();
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
BFile* GetFile() { return &fFile; }
|
||||||
|
|
||||||
|
const char* GetSectionHeaderStrings(size_t* size);
|
||||||
|
const char* GetStringSectionStrings(int32 index,
|
||||||
|
size_t* size);
|
||||||
|
|
||||||
|
int32 CountSections() const { return fSectionCount; }
|
||||||
|
ElfSection* SectionAt(int32 index, bool load = false);
|
||||||
|
|
||||||
|
void Dump();
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SetTo(const char *filename);
|
||||||
|
|
||||||
|
Elf32_Shdr* _SectionHeaderAt(int32 index);
|
||||||
|
|
||||||
|
status_t _LoadSection(int32 index);
|
||||||
|
|
||||||
|
private:
|
||||||
|
BFile fFile;
|
||||||
|
Elf32_Ehdr fHeader;
|
||||||
|
uint8* fSectionHeaders;
|
||||||
|
ElfSection* fSections;
|
||||||
|
int32 fSectionCount;
|
||||||
|
size_t fSectionHeaderSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ELF_FILE_H
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfImage.cpp
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Implementation of ElfImage, a class encapsulating
|
||||||
|
// a loaded ELF image, providing support for accessing the
|
||||||
|
// image's symbols and their relocation entries.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
#include "ElfImage.h"
|
||||||
|
|
||||||
|
// ElfImage
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfImage::ElfImage()
|
||||||
|
: fImage(-1),
|
||||||
|
fFile(),
|
||||||
|
fTextAddress(NULL),
|
||||||
|
fDataAddress(NULL),
|
||||||
|
fGotAddress(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfImage::~ElfImage()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTo
|
||||||
|
status_t
|
||||||
|
ElfImage::SetTo(image_id image)
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
status_t error = _SetTo(image);
|
||||||
|
if (error)
|
||||||
|
Unset();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfImage::Unset()
|
||||||
|
{
|
||||||
|
fFile.Unset();
|
||||||
|
fImage = -1;
|
||||||
|
fTextAddress = NULL;
|
||||||
|
fDataAddress = NULL;
|
||||||
|
fGotAddress = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload
|
||||||
|
void
|
||||||
|
ElfImage::Unload()
|
||||||
|
{
|
||||||
|
fFile.Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FindSymbol
|
||||||
|
status_t
|
||||||
|
ElfImage::FindSymbol(const char* symbolName, void** address)
|
||||||
|
{
|
||||||
|
return get_image_symbol(fImage, symbolName, B_SYMBOL_TYPE_ANY, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbolRelocations
|
||||||
|
status_t
|
||||||
|
ElfImage::GetSymbolRelocations(const char* symbolName, BList* relocations)
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
ElfRelocation relocation;
|
||||||
|
for (ElfRelocationIterator it(&fFile); it.GetNext(&relocation); ) {
|
||||||
|
uint32 type = relocation.GetType();
|
||||||
|
// get the symbol
|
||||||
|
ElfSymbol symbol;
|
||||||
|
if ((type == R_386_GLOB_DAT || type == R_386_JMP_SLOT)
|
||||||
|
&& relocation.GetSymbol(&symbol) == B_OK
|
||||||
|
&& symbol.GetName()) {
|
||||||
|
// only undefined symbols with global binding
|
||||||
|
if ((symbol.GetBinding() == STB_GLOBAL
|
||||||
|
|| symbol.GetBinding() == STB_WEAK)
|
||||||
|
&& (symbol.GetTargetSectionIndex() == SHN_UNDEF
|
||||||
|
|| symbol.GetTargetSectionIndex()
|
||||||
|
>= (uint32)fFile.CountSections())
|
||||||
|
&& !strcmp(symbol.GetName(), symbolName)) {
|
||||||
|
// get the address of the GOT entry for the symbol
|
||||||
|
void** gotEntry
|
||||||
|
= (void**)(fTextAddress + relocation.GetOffset());
|
||||||
|
if (!relocations->AddItem(gotEntry)) {
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _SetTo
|
||||||
|
status_t
|
||||||
|
ElfImage::_SetTo(image_id image)
|
||||||
|
{
|
||||||
|
// get an image info
|
||||||
|
image_info imageInfo;
|
||||||
|
status_t error = get_image_info(image, &imageInfo);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
fImage = imageInfo.id;
|
||||||
|
// get the address of global offset table
|
||||||
|
error = get_image_symbol(image, "_GLOBAL_OFFSET_TABLE_",
|
||||||
|
B_SYMBOL_TYPE_ANY, (void**)&fGotAddress);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
fTextAddress = (uint8*)imageInfo.text;
|
||||||
|
fDataAddress = (uint8*)imageInfo.data;
|
||||||
|
// init the file
|
||||||
|
error = fFile.SetTo(imageInfo.name);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfImage.h
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Interface declaration of ElfImage, a class encapsulating
|
||||||
|
// a loaded ELF image, providing support for accessing the
|
||||||
|
// image's symbols and their relocation entries.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef ELF_IMAGE_H
|
||||||
|
#define ELF_IMAGE_H
|
||||||
|
|
||||||
|
#include <File.h>
|
||||||
|
#include <image.h>
|
||||||
|
|
||||||
|
#include "ElfFile.h"
|
||||||
|
|
||||||
|
class BList;
|
||||||
|
class ElfSection;
|
||||||
|
class ElfSymbol;
|
||||||
|
|
||||||
|
// ElfImage
|
||||||
|
class ElfImage {
|
||||||
|
public:
|
||||||
|
ElfImage();
|
||||||
|
~ElfImage();
|
||||||
|
status_t SetTo(image_id image);
|
||||||
|
void Unset();
|
||||||
|
void Unload();
|
||||||
|
|
||||||
|
image_id GetID() const { return fImage; }
|
||||||
|
|
||||||
|
status_t FindSymbol(const char* symbolName,
|
||||||
|
void** address);
|
||||||
|
status_t GetSymbolRelocations(const char* symbolName,
|
||||||
|
BList* relocations);
|
||||||
|
|
||||||
|
private:
|
||||||
|
status_t _SetTo(image_id image);
|
||||||
|
|
||||||
|
private:
|
||||||
|
image_id fImage;
|
||||||
|
ElfFile fFile;
|
||||||
|
uint8* fTextAddress;
|
||||||
|
uint8* fDataAddress;
|
||||||
|
uint8* fGotAddress;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ELF_IMAGE_H
|
||||||
@@ -0,0 +1,627 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2003, Ingo Weinhold
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: ElfSymbolPatcher.cpp
|
||||||
|
// Author: Ingo Weinhold ([email protected])
|
||||||
|
// Description: Interface declaration of classes used for patching ELF
|
||||||
|
// symbols. Central class is ElfSymbolPatcher. It is a kind of
|
||||||
|
// roster, managing all necessary infos (loaded images) and
|
||||||
|
// being able to fill ElfSymbolPatchInfos with life.
|
||||||
|
// An ElfSymbolPatchInfo represents a symbol and is able to
|
||||||
|
// patch/restore it. An ElfSymbolPatchGroup bundles several
|
||||||
|
// ElfSymbolPatchInfos and can update their data, e.g.
|
||||||
|
// when images are loaded/unloaded. It uses a
|
||||||
|
// ElfSymbolPatcher internally and provides a more convenient
|
||||||
|
// API for the user.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "ElfImage.h"
|
||||||
|
#include "ElfSymbolPatcher.h"
|
||||||
|
|
||||||
|
/////////////////////////////
|
||||||
|
// ElfSymbolPatchInfo::Entry
|
||||||
|
//
|
||||||
|
|
||||||
|
class ElfSymbolPatchInfo::Entry {
|
||||||
|
public:
|
||||||
|
static Entry* Create(image_id image, void*** targets,
|
||||||
|
int32 targetCount);
|
||||||
|
void Delete();
|
||||||
|
|
||||||
|
image_id GetImage() const { return fImage; }
|
||||||
|
|
||||||
|
void Patch(void* newAddress);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Entry();
|
||||||
|
Entry(const Entry&);
|
||||||
|
Entry(image_id image, void*** targets,
|
||||||
|
int32 targetCount);
|
||||||
|
~Entry();
|
||||||
|
|
||||||
|
private:
|
||||||
|
image_id fImage;
|
||||||
|
int32 fPatchTargetCount;
|
||||||
|
void** fPatchTargets[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Create
|
||||||
|
ElfSymbolPatchInfo::Entry*
|
||||||
|
ElfSymbolPatchInfo::Entry::Create(image_id image, void*** targets,
|
||||||
|
int32 targetCount)
|
||||||
|
{
|
||||||
|
if (!targets || targetCount <= 0)
|
||||||
|
return NULL;
|
||||||
|
void* buffer = malloc(sizeof(Entry) + sizeof(void**) * (targetCount - 1));
|
||||||
|
Entry* entry = NULL;
|
||||||
|
if (buffer)
|
||||||
|
entry = new(buffer) Entry(image, targets, targetCount);
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete
|
||||||
|
void
|
||||||
|
ElfSymbolPatchInfo::Entry::Delete()
|
||||||
|
{
|
||||||
|
this->~Entry();
|
||||||
|
free(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch
|
||||||
|
void
|
||||||
|
ElfSymbolPatchInfo::Entry::Patch(void* newAddress)
|
||||||
|
{
|
||||||
|
//printf("ElfSymbolPatchInfo::Entry::Patch(): patching %ld addresses\n",
|
||||||
|
//fPatchTargetCount);
|
||||||
|
for (int i = 0; i < fPatchTargetCount; i++)
|
||||||
|
*fPatchTargets[i] = newAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbolPatchInfo::Entry::Entry(image_id image, void*** targets,
|
||||||
|
int32 targetCount)
|
||||||
|
: fImage(image),
|
||||||
|
fPatchTargetCount(targetCount)
|
||||||
|
{
|
||||||
|
memcpy(fPatchTargets + 0, targets, targetCount * sizeof(void**));
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbolPatchInfo::Entry::~Entry()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////
|
||||||
|
// ElfSymbolPatchInfo
|
||||||
|
//
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbolPatchInfo::ElfSymbolPatchInfo()
|
||||||
|
: fSymbolName(),
|
||||||
|
fOriginalAddress(NULL),
|
||||||
|
fOriginalAddressImage(-1),
|
||||||
|
fEntries()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbolPatchInfo::~ElfSymbolPatchInfo()
|
||||||
|
{
|
||||||
|
Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchInfo::InitCheck() const
|
||||||
|
{
|
||||||
|
return (fOriginalAddress && fSymbolName.Length() ? B_OK : B_NO_INIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbolName
|
||||||
|
const char*
|
||||||
|
ElfSymbolPatchInfo::GetSymbolName() const
|
||||||
|
{
|
||||||
|
return fSymbolName.String();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOriginalAddress
|
||||||
|
void*
|
||||||
|
ElfSymbolPatchInfo::GetOriginalAddress() const
|
||||||
|
{
|
||||||
|
return fOriginalAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetOriginalAddressImage
|
||||||
|
image_id
|
||||||
|
ElfSymbolPatchInfo::GetOriginalAddressImage() const
|
||||||
|
{
|
||||||
|
return fOriginalAddressImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchInfo::Patch(void* newAddress)
|
||||||
|
{
|
||||||
|
//printf("ElfSymbolPatchInfo::Patch(): patching %ld images\n",
|
||||||
|
//fEntries.CountItems());
|
||||||
|
status_t error = InitCheck();
|
||||||
|
if (error == B_OK) {
|
||||||
|
for (int i = 0; Entry* entry = EntryAt(i); i++)
|
||||||
|
entry->Patch(newAddress);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchInfo::Restore()
|
||||||
|
{
|
||||||
|
return Patch(fOriginalAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unset
|
||||||
|
void
|
||||||
|
ElfSymbolPatchInfo::Unset()
|
||||||
|
{
|
||||||
|
for (int i = 0; Entry* entry = EntryAt(i); i++)
|
||||||
|
entry->Delete();
|
||||||
|
fEntries.MakeEmpty();
|
||||||
|
fSymbolName.SetTo("");
|
||||||
|
fOriginalAddress = NULL;
|
||||||
|
fOriginalAddressImage = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetSymbolName
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchInfo::SetSymbolName(const char* name)
|
||||||
|
{
|
||||||
|
fSymbolName.SetTo(name);
|
||||||
|
if (name && fSymbolName != name)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetOriginalAddress
|
||||||
|
void
|
||||||
|
ElfSymbolPatchInfo::SetOriginalAddress(void* address, image_id image)
|
||||||
|
{
|
||||||
|
fOriginalAddress = address;
|
||||||
|
fOriginalAddressImage = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateEntry
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchInfo::CreateEntry(image_id image, BList* targets)
|
||||||
|
{
|
||||||
|
if (!targets || targets->CountItems() == 0)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
Entry* entry = Entry::Create(image, (void***)targets->Items(),
|
||||||
|
targets->CountItems());
|
||||||
|
if (!entry)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!fEntries.AddItem(entry)) {
|
||||||
|
entry->Delete();
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteEntry
|
||||||
|
bool
|
||||||
|
ElfSymbolPatchInfo::DeleteEntry(image_id image)
|
||||||
|
{
|
||||||
|
for (int i = 0; Entry* entry = EntryAt(i); i++) {
|
||||||
|
if (entry->GetImage() == image) {
|
||||||
|
fEntries.RemoveItem(i);
|
||||||
|
entry->Delete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntryAt
|
||||||
|
ElfSymbolPatchInfo::Entry*
|
||||||
|
ElfSymbolPatchInfo::EntryAt(int32 index)
|
||||||
|
{
|
||||||
|
return (Entry*)fEntries.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// EntryFor
|
||||||
|
ElfSymbolPatchInfo::Entry*
|
||||||
|
ElfSymbolPatchInfo::EntryFor(image_id image)
|
||||||
|
{
|
||||||
|
for (int i = 0; Entry* entry = EntryAt(i); i++) {
|
||||||
|
if (entry->GetImage() == image)
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////
|
||||||
|
// UpdateAdapter
|
||||||
|
//
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbolPatcher::UpdateAdapter::UpdateAdapter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbolPatcher::UpdateAdapter::~UpdateAdapter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageAdded
|
||||||
|
void
|
||||||
|
ElfSymbolPatcher::UpdateAdapter::ImageAdded(ElfImage* image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageRemoved
|
||||||
|
void
|
||||||
|
ElfSymbolPatcher::UpdateAdapter::ImageRemoved(ElfImage* image)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////
|
||||||
|
// ElfSymbolPatcher
|
||||||
|
//
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbolPatcher::ElfSymbolPatcher()
|
||||||
|
: fImages(),
|
||||||
|
fInitStatus(B_NO_INIT)
|
||||||
|
{
|
||||||
|
fInitStatus = _Init();
|
||||||
|
if (fInitStatus != B_OK)
|
||||||
|
_Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbolPatcher::~ElfSymbolPatcher()
|
||||||
|
{
|
||||||
|
_Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitCheck
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatcher::InitCheck() const
|
||||||
|
{
|
||||||
|
return fInitStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatcher::Update(UpdateAdapter* updateAdapter)
|
||||||
|
{
|
||||||
|
if (InitCheck() != B_OK)
|
||||||
|
return B_NO_INIT;
|
||||||
|
// remove obsolete images
|
||||||
|
int32 count = fImages.CountItems();
|
||||||
|
for (int i = count - 1; i >= 0; i--) {
|
||||||
|
ElfImage* image = _ImageAt(i);
|
||||||
|
image_info info;
|
||||||
|
if (get_image_info(image->GetID(), &info) != B_OK) {
|
||||||
|
if (updateAdapter)
|
||||||
|
updateAdapter->ImageRemoved(image);
|
||||||
|
fImages.RemoveItem(i);
|
||||||
|
delete image;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add new images
|
||||||
|
status_t error = B_OK;
|
||||||
|
image_info info;
|
||||||
|
int32 cookie = 0;
|
||||||
|
while (get_next_image_info(0, &cookie, &info) == B_OK) {
|
||||||
|
ElfImage* image = _ImageForID(info.id);
|
||||||
|
if (image)
|
||||||
|
continue;
|
||||||
|
image = new(nothrow) ElfImage;
|
||||||
|
if (!image)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!fImages.AddItem(image)) {
|
||||||
|
delete image;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
error = image->SetTo(info.id);
|
||||||
|
if (updateAdapter)
|
||||||
|
updateAdapter->ImageAdded(image);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unload
|
||||||
|
void
|
||||||
|
ElfSymbolPatcher::Unload()
|
||||||
|
{
|
||||||
|
for (int i = 0; ElfImage* image = _ImageAt(i); i++)
|
||||||
|
image->Unload();
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSymbolPatchInfo
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatcher::GetSymbolPatchInfo(const char* symbolName,
|
||||||
|
ElfSymbolPatchInfo* info)
|
||||||
|
{
|
||||||
|
// check parameters and intialization
|
||||||
|
if (!symbolName || !info)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
if (InitCheck() != B_OK)
|
||||||
|
return B_NO_INIT;
|
||||||
|
// set the symbol name
|
||||||
|
info->Unset();
|
||||||
|
status_t error = info->SetSymbolName(symbolName);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
for (int i = 0; ElfImage* image = _ImageAt(i); i++) {
|
||||||
|
//printf("searching in image: %ld\n", image->GetID());
|
||||||
|
// get the symbol's relocations
|
||||||
|
BList patchTargets;
|
||||||
|
error = image->GetSymbolRelocations(symbolName, &patchTargets);
|
||||||
|
if (error != B_OK)
|
||||||
|
break;
|
||||||
|
if (patchTargets.CountItems() > 0) {
|
||||||
|
error = info->CreateEntry(image->GetID(), &patchTargets);
|
||||||
|
if (error != B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// get the symbol's address
|
||||||
|
void* address = NULL;
|
||||||
|
if (image->FindSymbol(symbolName, &address) == B_OK && address) {
|
||||||
|
if (info->GetOriginalAddress()) {
|
||||||
|
// A symbol with that name lives in at least two images.
|
||||||
|
// Better bail out.
|
||||||
|
//printf("Found the symbol in more than one image!\n");
|
||||||
|
error = B_ERROR;
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
info->SetOriginalAddress(address, image->GetID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// set the symbol address
|
||||||
|
if (!info->GetOriginalAddress())
|
||||||
|
{
|
||||||
|
//printf("Symbol not found in any image!\n");
|
||||||
|
error = B_ERROR;
|
||||||
|
}
|
||||||
|
// cleanup on error
|
||||||
|
if (error != B_OK)
|
||||||
|
info->Unset();
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateSymbolPatchInfo
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatcher::UpdateSymbolPatchInfo(ElfSymbolPatchInfo* info,
|
||||||
|
ElfImage* image)
|
||||||
|
{
|
||||||
|
if (!info || !image || !info->GetSymbolName())
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
// get the symbol's relocations
|
||||||
|
BList patchTargets;
|
||||||
|
status_t error
|
||||||
|
= image->GetSymbolRelocations(info->GetSymbolName(), &patchTargets);
|
||||||
|
if (error == B_OK)
|
||||||
|
error = info->CreateEntry(image->GetID(), &patchTargets);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _Init
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatcher::_Init()
|
||||||
|
{
|
||||||
|
status_t error = B_OK;
|
||||||
|
image_info info;
|
||||||
|
int32 cookie = 0;
|
||||||
|
while (get_next_image_info(0, &cookie, &info) == B_OK) {
|
||||||
|
ElfImage* image = new(nothrow) ElfImage;
|
||||||
|
if (!image)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
if (!fImages.AddItem(image)) {
|
||||||
|
delete image;
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
error = image->SetTo(info.id);
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// _Cleanup
|
||||||
|
void
|
||||||
|
ElfSymbolPatcher::_Cleanup()
|
||||||
|
{
|
||||||
|
for (int i = 0; ElfImage* image = _ImageAt(i); i++)
|
||||||
|
delete image;
|
||||||
|
fImages.MakeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ImageAt
|
||||||
|
ElfImage*
|
||||||
|
ElfSymbolPatcher::_ImageAt(int32 index) const
|
||||||
|
{
|
||||||
|
return (ElfImage*)fImages.ItemAt(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// _ImageForID
|
||||||
|
ElfImage*
|
||||||
|
ElfSymbolPatcher::_ImageForID(image_id id) const
|
||||||
|
{
|
||||||
|
for (int i = 0; ElfImage* image = _ImageAt(i); i++) {
|
||||||
|
if (image->GetID() == id)
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////
|
||||||
|
// ElfSymbolPatchGroup
|
||||||
|
//
|
||||||
|
|
||||||
|
// constructor
|
||||||
|
ElfSymbolPatchGroup::ElfSymbolPatchGroup(ElfSymbolPatcher* patcher)
|
||||||
|
: fPatcher(patcher),
|
||||||
|
fPatchInfos(),
|
||||||
|
fOwnsPatcher(false),
|
||||||
|
fPatched(false)
|
||||||
|
{
|
||||||
|
// create a patcher if none has been supplied
|
||||||
|
if (!fPatcher) {
|
||||||
|
fPatcher = new(nothrow) ElfSymbolPatcher;
|
||||||
|
if (fPatcher) {
|
||||||
|
if (fPatcher->InitCheck() == B_OK)
|
||||||
|
fOwnsPatcher = true;
|
||||||
|
else {
|
||||||
|
delete fPatcher;
|
||||||
|
fPatcher = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// destructor
|
||||||
|
ElfSymbolPatchGroup::~ElfSymbolPatchGroup()
|
||||||
|
{
|
||||||
|
RemoveAllPatches();
|
||||||
|
if (fPatcher && fOwnsPatcher)
|
||||||
|
delete fPatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddPatch
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchGroup::AddPatch(const char* symbolName, void* newAddress,
|
||||||
|
void** originalAddress)
|
||||||
|
{
|
||||||
|
// check initialization and parameters
|
||||||
|
if (!fPatcher)
|
||||||
|
return B_NO_INIT;
|
||||||
|
if (!symbolName || !originalAddress)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
// allocate patch info
|
||||||
|
PatchInfo* patchInfo = new(nothrow) PatchInfo;
|
||||||
|
if (!patchInfo)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
// init and add the patch info
|
||||||
|
status_t error = fPatcher->GetSymbolPatchInfo(symbolName, patchInfo);
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (fPatchInfos.AddItem(patchInfo)) {
|
||||||
|
patchInfo->fNewAddress = newAddress;
|
||||||
|
*originalAddress = patchInfo->GetOriginalAddress();
|
||||||
|
} else
|
||||||
|
error = B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
// cleanup on failure
|
||||||
|
if (error != B_OK && patchInfo) {
|
||||||
|
fPatchInfos.RemoveItem(patchInfo);
|
||||||
|
delete patchInfo;
|
||||||
|
}
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveAllPatches
|
||||||
|
void
|
||||||
|
ElfSymbolPatchGroup::RemoveAllPatches()
|
||||||
|
{
|
||||||
|
for (int i = 0; PatchInfo* info = (PatchInfo*)fPatchInfos.ItemAt(i); i++)
|
||||||
|
delete info;
|
||||||
|
fPatchInfos.MakeEmpty();
|
||||||
|
fPatched = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Patch
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchGroup::Patch()
|
||||||
|
{
|
||||||
|
//printf("ElfSymbolPatchGroup::Patch(): patching %ld symbols\n",
|
||||||
|
//fPatchInfos.CountItems());
|
||||||
|
if (!fPatcher)
|
||||||
|
return B_NO_INIT;
|
||||||
|
if (fPatched)
|
||||||
|
return B_OK;
|
||||||
|
for (int i = 0; PatchInfo* info = (PatchInfo*)fPatchInfos.ItemAt(i); i++)
|
||||||
|
info->Patch(info->fNewAddress);
|
||||||
|
fPatched = true;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchGroup::Restore()
|
||||||
|
{
|
||||||
|
if (!fPatcher)
|
||||||
|
return B_NO_INIT;
|
||||||
|
if (!fPatched)
|
||||||
|
return B_OK;
|
||||||
|
for (int i = 0; PatchInfo* info = (PatchInfo*)fPatchInfos.ItemAt(i); i++)
|
||||||
|
info->Restore();
|
||||||
|
fPatched = false;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update
|
||||||
|
status_t
|
||||||
|
ElfSymbolPatchGroup::Update()
|
||||||
|
{
|
||||||
|
if (!fPatcher)
|
||||||
|
return B_NO_INIT;
|
||||||
|
return fPatcher->Update(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageAdded
|
||||||
|
void
|
||||||
|
ElfSymbolPatchGroup::ImageAdded(ElfImage* image)
|
||||||
|
{
|
||||||
|
for (int i = 0; PatchInfo* info = (PatchInfo*)fPatchInfos.ItemAt(i); i++) {
|
||||||
|
fPatcher->UpdateSymbolPatchInfo(info, image);
|
||||||
|
if (fPatched) {
|
||||||
|
ElfSymbolPatchInfo::Entry* entry = info->EntryFor(image->GetID());
|
||||||
|
if (entry)
|
||||||
|
info->Patch(info->fNewAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImageRemoved
|
||||||
|
void
|
||||||
|
ElfSymbolPatchGroup::ImageRemoved(ElfImage* image)
|
||||||
|
{
|
||||||
|
int32 count = fPatchInfos.CountItems();
|
||||||
|
for (int i = count - 1; i >= 0; i--) {
|
||||||
|
PatchInfo* info = (PatchInfo*)fPatchInfos.ItemAt(i);
|
||||||
|
if (info->GetOriginalAddressImage() == image->GetID()) {
|
||||||
|
// the image the symbol lives in, has been removed: remove the
|
||||||
|
// complete patch info
|
||||||
|
fPatchInfos.RemoveItem(i);
|
||||||
|
delete info;
|
||||||
|
} else
|
||||||
|
info->DeleteEntry(image->GetID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
SubDir OBOS_TOP src tools elfsymbolpatcher ;
|
||||||
|
|
||||||
|
UseHeaders [ FDirName $(OBOS_TOP) headers tools elfsymbolpatcher ] ;
|
||||||
|
|
||||||
|
StaticLibrary elfsymbolpatcher
|
||||||
|
: ElfFile.cpp
|
||||||
|
ElfImage.cpp
|
||||||
|
ElfSymbolPatcher.cpp
|
||||||
|
;
|
||||||
Reference in New Issue
Block a user