X-Git-Url: https://git.enpas.org/?a=blobdiff_plain;f=include%2Flibelfu%2Fmodelops.h;fp=include%2Flibelfu%2Fmodelops.h;h=92f863fd6b7b59d112a67c38e3d0f086619c8ff9;hb=50b85e44529f195bf8156e9c0045d8b017ee26f5;hp=538e97a6207fd4705ace7ff773cc7b5f6d5fbb25;hpb=28507233568a6deb80e243bd82df1e93f0b136a0;p=centaur.git diff --git a/include/libelfu/modelops.h b/include/libelfu/modelops.h index 538e97a..92f863f 100644 --- a/include/libelfu/modelops.h +++ b/include/libelfu/modelops.h @@ -1,3 +1,15 @@ +/*! + * @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__ @@ -7,74 +19,396 @@ #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)) - int elfu_mSymtabLookupSymToAddr(ElfuElf *me, ElfuScn *msst, ElfuSym *sym, GElf_Addr *result); - char* elfu_mSymtabSymToName(ElfuScn *msst, ElfuSym *sym); - ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry); +/*! + * @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); - void elfu_mSymtabFlatten(ElfuElf *me); - void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me); + +/*! + * @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); - void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2); - size_t elfu_mPhdrCount(ElfuElf *me); + +/*! + * @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); - void elfu_mPhdrLoadLowestHighest(ElfuElf *me, - ElfuPhdr **lowestAddr, - ElfuPhdr **highestAddr, - ElfuPhdr **lowestOffs, - ElfuPhdr **highestOffsEnd); - void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp); + +/*! + * @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(); - void elfu_mPhdrDestroy(ElfuPhdr* mp); + +/*! + * @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); - void* elfu_mScnForall(ElfuElf *me, SectionHandlerFunc f, void *aux1, void *aux2); - size_t elfu_mScnCount(ElfuElf *me); - size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms); - ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn); - char* elfu_mScnName(ElfuElf *me, ElfuScn *ms); + +/*! + * @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); - int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len); - ElfuScn* elfu_mScnAlloc(); - void elfu_mScnDestroy(ElfuScn* ms); + +/*! + * @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(); - void elfu_mElfDestroy(ElfuElf* me); + +/*! + * @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); - void elfu_mToElf(ElfuElf *me, Elf *e); - int elfu_mReladd(ElfuElf *me, const ElfuElf *mrel); +/*! + * @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