/* This file is part of centaur.
*
* centaur is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License 2 as
* published by the Free Software Foundation.
* centaur is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with centaur. If not, see .
*/
/*!
* @file modelops.h
* @brief Operations offered on libelfu's Elfu* models.
*
* This includes:
* - Allocation/initialization, teardown of objects
* - Iteration (*Forall)
* - Stats (counts, lowest/highest element, ...)
* - Lookups (addresses, ...)
* - Scripted high-level operations (reladd, detour, ...)
*/
#ifndef __LIBELFU_MODELOPS_H__
#define __LIBELFU_MODELOPS_H__
#include
#include
#include
/*!
* @brief Lookup name of a string.
* @param symtabscn ElfuScn of symbol table.
* @param off Offset in string table at which name starts.
* @result Pointer to name.
* @result INTERNAL USE ONLY.
* See elfu_mSymtabSymToName() for an alternative.
*
*/
#define ELFU_SYMSTR(symtabscn, off) ((symtabscn)->linkptr->databuf + (off))
/*!
* @brief Lookup the address a symbol points to.
* @param me Entire ELF model.
* @param msst ElfuScn containing the symbol table this symbol is in.
* @param sym The symbol itself.
* @param result Will be set to the calculated address.
* @result 0 if *result is valid. Otherwise, *result is undefined and the
* address could not be resolved.
* @note This is currently for INTERNAL USE in the relocator ONLY.
*/
int elfu_mSymtabLookupSymToAddr(ElfuElf *me, ElfuScn *msst, ElfuSym *sym, GElf_Addr *result);
/*!
* @brief Lookup name of a symbol.
* @param msst ElfuScn containing the symbol table this symbol is in.
* @param sym The symbol itself.
* @result Pointer to name.
*/
char* elfu_mSymtabSymToName(ElfuScn *msst, ElfuSym *sym);
/*!
* @brief Lookup a symbol by its index in a symbol table.
* @param msst ElfuScn containing the symbol table this symbol is in.
* @param entry The symbol's index in the table.
* @result Pointer to the symbol.
*/
ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry);
/*!
* @brief Lookup the address a symbol points to, by the symbol name.
* @param me Entire ELF model.
* @param msst ElfuScn containing the symbol table this symbol is in.
* @param name The symbol's name.
* @result The address the symbol points to.
*/
GElf_Addr elfu_mSymtabLookupAddrByName(ElfuElf *me, ElfuScn *msst, char *name);
/*!
* @brief Serialize an ELF's global symbol table.
* @param me Entire ELF model.
*/
void elfu_mSymtabFlatten(ElfuElf *me);
/*!
* @brief Check if a global symbol table exists, and add it otherwise.
* @param me Entire ELF model.
*/
void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me);
/*!
* @brief Callback for elfu_mPhdrForall().
* @param me Entire ELF model.
* @param mp Current PHDR to process.
* @param aux1 User defined.
* @param aux2 User defined.
* @result NULL if iteration is to continue.
* Otherwise it is aborted and the handler's return value is
* returned by elfu_mPhdrForall() itself.
*/
typedef void* (PhdrHandlerFunc)(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2);
/*!
* @brief Iterate over all PHDRs.
* @param me Entire ELF model.
* @param f Callback function.
* @param aux1 User defined.
* @param aux2 User defined.
* @result NULL if all items have been processed.
* Otherwise the return value of the last handler function
* call before aborting.
*/
void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2);
/*!
* @brief Calculate number of PHDRs in an ElfuElf.
* @param me Entire ELF model.
* @result Total number of PHDRs.
*/
size_t elfu_mPhdrCount(ElfuElf *me);
/*!
* @brief Find a PHDR that covers a memory address.
* @param me Entire ELF model.
* @param addr A memory address.
* @result Pointer to a PHDR containing the given memory address.
* NULL if none found.
*/
ElfuPhdr* elfu_mPhdrByAddr(ElfuElf *me, GElf_Addr addr);
/*!
* @brief Find a PHDR that covers a file offset.
* @param me Entire ELF model.
* @param offset A file offset.
* @result Pointer to a PHDR containing the given file offset.
* NULL if none found.
*/
ElfuPhdr* elfu_mPhdrByOffset(ElfuElf *me, GElf_Off offset);
/*!
* @brief Find the ElfuElf's memory address and file offset
* extrema in terms of PHDRs.
* @param me Entire ELF model.
* @param lowestAddr Will be set to PHDR containing the lowest address referenced.
* @param highestAddr Will be set to PHDR containing the highest address referenced.
* @param lowestOffs Will be set to PHDR containing the lowest offset referenced.
* @param highestOffsEnd Will be set to PHDR containing the highest offset referenced.
*/
void elfu_mPhdrLoadLowestHighest(ElfuElf *me,
ElfuPhdr **lowestAddr,
ElfuPhdr **highestAddr,
ElfuPhdr **lowestOffs,
ElfuPhdr **highestOffsEnd);
/*!
* @brief Update child sections' offsets in the file according to parent
* PHDR's offset and address.
* @param mp Parent PHDR whose children to update.
*/
void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp);
/*!
* @brief Allocate and initialize a PHDR model.
* @result Pointer to a fresh ElfuPhdr.
* NULL if allocation failed.
*/
ElfuPhdr* elfu_mPhdrAlloc();
/*!
* @brief Tear down a PHDR and its children.
* @param mp PHDR to delete.
*/
void elfu_mPhdrDestroy(ElfuPhdr* mp);
/*!
* @brief Callback for elfu_mScnForall().
* @param me Entire ELF model.
* @param ms Current section to process.
* @param aux1 User defined.
* @param aux2 User defined.
* @result NULL if iteration is to continue.
* Otherwise it is aborted and the handler's return value is
* returned by elfu_mScnForall() itself.
*/
typedef void* (SectionHandlerFunc)(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2);
/*!
* @brief Iterate over all sections.
* @param me Entire ELF model.
* @param f Callback function.
* @param aux1 User defined.
* @param aux2 User defined.
* @result NULL if all items have been processed.
* Otherwise the return value of the last handler function
* call before aborting.
*/
void* elfu_mScnForall(ElfuElf *me, SectionHandlerFunc f, void *aux1, void *aux2);
/*!
* @brief Calculate number of sections in an ElfuElf.
* @param me Entire ELF model.
* @result Total number of sections.
*/
size_t elfu_mScnCount(ElfuElf *me);
/*!
* @brief Calculate index a section would currently have in its ElfuElf.
* @param me Entire ELF model.
* @param ms A section in *me.
* @result Estimated index.
*/
size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms);
/*!
* @brief Find a cloned section by its oldscn value.
* @param me Entire ELF model.
* @param oldscn Original section to find the clone of.
* @result A section that is a clone of *oldscn.
* NULL if none found.
*/
ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn);
/*!
* @brief Get a section's name.
* @param me Entire ELF model.
* @param ms A section in *me.
* @result Pointer to the section's name in .shstrtab.
*/
char* elfu_mScnName(ElfuElf *me, ElfuScn *ms);
/*!
* @brief Allocate an array of pointers to all sections,
* and sort them by offset.
* @param me Entire ELF model.
* @param count Where to write total count of sections to.
* @result Pointer to the section's name in .shstrtab.
* NULL if an error occurred.
*/
ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count);
/*!
* @brief Enlarge a section's buffer and append data to it.
* @param ms Section to append to.
* @param buf Source buffer with data to append.
* @param len Length of source buffer.
* @result 0 if successful.
* Anything else indicates an error.
*/
int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len);
/*!
* @brief Allocate and initialize a section model.
* @result Pointer to a fresh ElfuScn.
* NULL if allocation failed.
*/
ElfuScn* elfu_mScnAlloc();
/*!
* @brief Tear down a section and associated buffers.
* @param ms Section to delete.
*/
void elfu_mScnDestroy(ElfuScn* ms);
/*!
* @brief Allocate and initialize an ELF file model.
* @result Pointer to a fresh ElfuElf.
* NULL if allocation failed.
*/
ElfuElf* elfu_mElfAlloc();
/*!
* @brief Tear down an ELF file model and associated structures.
* @param me ElfuElf to destroy.
*/
void elfu_mElfDestroy(ElfuElf* me);
/*!
* @brief Find a LOAD segment to inject into, and expand/create it.
* @param me Entire ELF model.
* @param size Size of data to inject.
* @param align Alignment requirement of new data.
* @param w Whether the new data should be writable when loaded.
* @param x Whether the new data should be executable when loaded.
* @param injPhdr Will be set to the identified target PHDR.
* @result The address where the data will be located.
*/
GElf_Addr elfu_mLayoutGetSpaceInPhdr(ElfuElf *me, GElf_Word size,
GElf_Word align, int w, int x,
ElfuPhdr **injPhdr);
/*!
* @brief Re-layout an ELF file so nothing overlaps that should not.
* Also, recalculate various offsets and sizes where necessary.
* @param me Entire ELF model.
*/
int elfu_mLayoutAuto(ElfuElf *me);
/*!
* @brief Lookup the address of a function in the PLT by its name.
* @param me Entire ELF model.
* @param name The function's name.
* @param result Will be set to the calculated address.
* @result 0 if *result is valid. Otherwise, *result is undefined and the
* address could not be resolved.
*/
int elfu_mDynLookupPltAddrByName(ElfuElf *me, char *name, GElf_Addr *result);
/*!
* @brief Lookup the address of a dynamically loaded variable by its name.
* @param me Entire ELF model.
* @param name The variable's name.
* @param result Will be set to the calculated address.
* @result 0 if *result is valid. Otherwise, *result is undefined and the
* address could not be resolved.
*/
int elfu_mDynLookupReldynAddrByName(ElfuElf *me, char *name, GElf_Addr *result);
/*!
* @brief Relocate a section.
* @param metarget ELF model containing cloned section.
* @param mstarget Cloned section to be relocated.
* @param msrt Section in original ELF model,
* containing relocation table.
* @result 0 if successful.
* Anything else indicates an error.
* @note This is currently for INTERNAL USE in Reladd ONLY.
*/
int elfu_mRelocate(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt);
/*!
* @brief Perform a few sanity checks.
* @param me Entire ELF model.
* @result 0 if successful.
* Anything else indicates an error.
*/
int elfu_mCheck(ElfuElf *me);
/*!
* @brief Dump contents of a PHDR to stdout.
* @param me Entire ELF model.
* @param mp PHDR to dump.
*/
void elfu_mDumpPhdr(ElfuElf *me, ElfuPhdr *mp);
/*!
* @brief Dump details of a section to stdout.
* @param me Entire ELF model.
* @param ms Section to dump.
*/
void elfu_mDumpScn(ElfuElf *me, ElfuScn *ms);
/*!
* @brief Dump contents of an entire ELF file model to stdout.
* @param me Entire ELF model to dump.
*/
void elfu_mDumpElf(ElfuElf *me);
/*!
* @brief Parse an ELF file to a libelfu model via libelf.
* @param e libelf handle to source file.
* @result NULL if an error occurred, a fresh ElfuElf otherwise.
*/
ElfuElf* elfu_mFromElf(Elf *e);
/*!
* @brief Serialize a libelfu model to an ELF file via libelf.
* @param me Entire ELF model.
* @param e libelf handle to destination file.
*/
void elfu_mToElf(ElfuElf *me, Elf *e);
/*!
* @brief Inject contents of an object file into an executable.
* @param me Destination ELF model.
* @param mrel Source ELF model.
* @result 0 if successful.
* Anything else indicates an error.
*/
int elfu_mReladd(ElfuElf *me, const ElfuElf *mrel);
/*!
* @brief Overwrite a location with an unconditional jump.
* @param me Entire ELF model.
* @param from Memory address to overwrite at.
* @param to Memory address to jump to.
*/
void elfu_mDetour(ElfuElf *me, GElf_Addr from, GElf_Addr to);
#endif