1 /* This file is part of centaur.
3 * centaur is free software: you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License 2 as
5 * published by the Free Software Foundation.
7 * centaur is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with centaur. If not, see <http://www.gnu.org/licenses/>.
18 * @brief Operations offered on libelfu's Elfu* models.
21 * - Allocation/initialization, teardown of objects
22 * - Iteration (*Forall)
23 * - Stats (counts, lowest/highest element, ...)
24 * - Lookups (addresses, ...)
25 * - Scripted high-level operations (reladd, detour, ...)
28 #ifndef __LIBELFU_MODELOPS_H__
29 #define __LIBELFU_MODELOPS_H__
34 #include <libelfu/types.h>
38 * @brief Lookup name of a string.
39 * @param symtabscn ElfuScn of symbol table.
40 * @param off Offset in string table at which name starts.
41 * @result Pointer to name.
42 * @result INTERNAL USE ONLY.
43 * See elfu_mSymtabSymToName() for an alternative.
46 #define ELFU_SYMSTR(symtabscn, off) ((symtabscn)->linkptr->databuf + (off))
50 * @brief Lookup the address a symbol points to.
51 * @param me Entire ELF model.
52 * @param msst ElfuScn containing the symbol table this symbol is in.
53 * @param sym The symbol itself.
54 * @param result Will be set to the calculated address.
55 * @result 0 if *result is valid. Otherwise, *result is undefined and the
56 * address could not be resolved.
57 * @note This is currently for INTERNAL USE in the relocator ONLY.
59 int elfu_mSymtabLookupSymToAddr(ElfuElf *me, ElfuScn *msst, ElfuSym *sym, GElf_Addr *result);
62 * @brief Lookup name of a symbol.
63 * @param msst ElfuScn containing the symbol table this symbol is in.
64 * @param sym The symbol itself.
65 * @result Pointer to name.
67 char* elfu_mSymtabSymToName(ElfuScn *msst, ElfuSym *sym);
70 * @brief Lookup a symbol by its index in a symbol table.
71 * @param msst ElfuScn containing the symbol table this symbol is in.
72 * @param entry The symbol's index in the table.
73 * @result Pointer to the symbol.
75 ElfuSym* elfu_mSymtabIndexToSym(ElfuScn *msst, GElf_Word entry);
78 * @brief Lookup the address a symbol points to, by the symbol name.
79 * @param me Entire ELF model.
80 * @param msst ElfuScn containing the symbol table this symbol is in.
81 * @param name The symbol's name.
82 * @result The address the symbol points to.
84 GElf_Addr elfu_mSymtabLookupAddrByName(ElfuElf *me, ElfuScn *msst, char *name);
87 * @brief Serialize an ELF's global symbol table.
88 * @param me Entire ELF model.
90 void elfu_mSymtabFlatten(ElfuElf *me);
93 * @brief Check if a global symbol table exists, and add it otherwise.
94 * @param me Entire ELF model.
96 void elfu_mSymtabAddGlobalDymtabIfNotPresent(ElfuElf *me);
102 * @brief Callback for elfu_mPhdrForall().
103 * @param me Entire ELF model.
104 * @param mp Current PHDR to process.
105 * @param aux1 User defined.
106 * @param aux2 User defined.
107 * @result NULL if iteration is to continue.
108 * Otherwise it is aborted and the handler's return value is
109 * returned by elfu_mPhdrForall() itself.
111 typedef void* (PhdrHandlerFunc)(ElfuElf *me, ElfuPhdr *mp, void *aux1, void *aux2);
114 * @brief Iterate over all PHDRs.
115 * @param me Entire ELF model.
116 * @param f Callback function.
117 * @param aux1 User defined.
118 * @param aux2 User defined.
119 * @result NULL if all items have been processed.
120 * Otherwise the return value of the last handler function
121 * call before aborting.
123 void* elfu_mPhdrForall(ElfuElf *me, PhdrHandlerFunc f, void *aux1, void *aux2);
126 * @brief Calculate number of PHDRs in an ElfuElf.
127 * @param me Entire ELF model.
128 * @result Total number of PHDRs.
130 size_t elfu_mPhdrCount(ElfuElf *me);
133 * @brief Find a PHDR that covers a memory address.
134 * @param me Entire ELF model.
135 * @param addr A memory address.
136 * @result Pointer to a PHDR containing the given memory address.
137 * NULL if none found.
139 ElfuPhdr* elfu_mPhdrByAddr(ElfuElf *me, GElf_Addr addr);
142 * @brief Find a PHDR that covers a file offset.
143 * @param me Entire ELF model.
144 * @param offset A file offset.
145 * @result Pointer to a PHDR containing the given file offset.
146 * NULL if none found.
148 ElfuPhdr* elfu_mPhdrByOffset(ElfuElf *me, GElf_Off offset);
151 * @brief Find the ElfuElf's memory address and file offset
152 * extrema in terms of PHDRs.
153 * @param me Entire ELF model.
154 * @param lowestAddr Will be set to PHDR containing the lowest address referenced.
155 * @param highestAddr Will be set to PHDR containing the highest address referenced.
156 * @param lowestOffs Will be set to PHDR containing the lowest offset referenced.
157 * @param highestOffsEnd Will be set to PHDR containing the highest offset referenced.
159 void elfu_mPhdrLoadLowestHighest(ElfuElf *me,
160 ElfuPhdr **lowestAddr,
161 ElfuPhdr **highestAddr,
162 ElfuPhdr **lowestOffs,
163 ElfuPhdr **highestOffsEnd);
166 * @brief Update child sections' offsets in the file according to parent
167 * PHDR's offset and address.
168 * @param mp Parent PHDR whose children to update.
170 void elfu_mPhdrUpdateChildOffsets(ElfuPhdr *mp);
173 * @brief Allocate and initialize a PHDR model.
174 * @result Pointer to a fresh ElfuPhdr.
175 * NULL if allocation failed.
177 ElfuPhdr* elfu_mPhdrAlloc();
180 * @brief Tear down a PHDR and its children.
181 * @param mp PHDR to delete.
183 void elfu_mPhdrDestroy(ElfuPhdr* mp);
189 * @brief Callback for elfu_mScnForall().
190 * @param me Entire ELF model.
191 * @param ms Current section to process.
192 * @param aux1 User defined.
193 * @param aux2 User defined.
194 * @result NULL if iteration is to continue.
195 * Otherwise it is aborted and the handler's return value is
196 * returned by elfu_mScnForall() itself.
198 typedef void* (SectionHandlerFunc)(ElfuElf *me, ElfuScn *ms, void *aux1, void *aux2);
201 * @brief Iterate over all sections.
202 * @param me Entire ELF model.
203 * @param f Callback function.
204 * @param aux1 User defined.
205 * @param aux2 User defined.
206 * @result NULL if all items have been processed.
207 * Otherwise the return value of the last handler function
208 * call before aborting.
210 void* elfu_mScnForall(ElfuElf *me, SectionHandlerFunc f, void *aux1, void *aux2);
213 * @brief Calculate number of sections in an ElfuElf.
214 * @param me Entire ELF model.
215 * @result Total number of sections.
217 size_t elfu_mScnCount(ElfuElf *me);
220 * @brief Calculate index a section would currently have in its ElfuElf.
221 * @param me Entire ELF model.
222 * @param ms A section in *me.
223 * @result Estimated index.
225 size_t elfu_mScnIndex(ElfuElf *me, ElfuScn *ms);
228 * @brief Find a cloned section by its oldscn value.
229 * @param me Entire ELF model.
230 * @param oldscn Original section to find the clone of.
231 * @result A section that is a clone of *oldscn.
232 * NULL if none found.
234 ElfuScn* elfu_mScnByOldscn(ElfuElf *me, ElfuScn *oldscn);
237 * @brief Get a section's name.
238 * @param me Entire ELF model.
239 * @param ms A section in *me.
240 * @result Pointer to the section's name in .shstrtab.
242 char* elfu_mScnName(ElfuElf *me, ElfuScn *ms);
245 * @brief Allocate an array of pointers to all sections,
246 * and sort them by offset.
247 * @param me Entire ELF model.
248 * @param count Where to write total count of sections to.
249 * @result Pointer to the section's name in .shstrtab.
250 * NULL if an error occurred.
252 ElfuScn** elfu_mScnSortedByOffset(ElfuElf *me, size_t *count);
255 * @brief Enlarge a section's buffer and append data to it.
256 * @param ms Section to append to.
257 * @param buf Source buffer with data to append.
258 * @param len Length of source buffer.
259 * @result 0 if successful.
260 * Anything else indicates an error.
262 int elfu_mScnAppendData(ElfuScn *ms, void *buf, size_t len);
265 * @brief Allocate and initialize a section model.
266 * @result Pointer to a fresh ElfuScn.
267 * NULL if allocation failed.
269 ElfuScn* elfu_mScnAlloc();
272 * @brief Tear down a section and associated buffers.
273 * @param ms Section to delete.
275 void elfu_mScnDestroy(ElfuScn* ms);
281 * @brief Allocate and initialize an ELF file model.
282 * @result Pointer to a fresh ElfuElf.
283 * NULL if allocation failed.
285 ElfuElf* elfu_mElfAlloc();
288 * @brief Tear down an ELF file model and associated structures.
289 * @param me ElfuElf to destroy.
291 void elfu_mElfDestroy(ElfuElf* me);
297 * @brief Find a LOAD segment to inject into, and expand/create it.
298 * @param me Entire ELF model.
299 * @param size Size of data to inject.
300 * @param align Alignment requirement of new data.
301 * @param w Whether the new data should be writable when loaded.
302 * @param x Whether the new data should be executable when loaded.
303 * @param injPhdr Will be set to the identified target PHDR.
304 * @result The address where the data will be located.
306 GElf_Addr elfu_mLayoutGetSpaceInPhdr(ElfuElf *me, GElf_Word size,
307 GElf_Word align, int w, int x,
310 * @brief Re-layout an ELF file so nothing overlaps that should not.
311 * Also, recalculate various offsets and sizes where necessary.
312 * @param me Entire ELF model.
314 int elfu_mLayoutAuto(ElfuElf *me);
320 * @brief Lookup the address of a function in the PLT by its name.
321 * @param me Entire ELF model.
322 * @param name The function's name.
323 * @param result Will be set to the calculated address.
324 * @result 0 if *result is valid. Otherwise, *result is undefined and the
325 * address could not be resolved.
327 int elfu_mDynLookupPltAddrByName(ElfuElf *me, char *name, GElf_Addr *result);
330 * @brief Lookup the address of a dynamically loaded variable by its name.
331 * @param me Entire ELF model.
332 * @param name The variable's name.
333 * @param result Will be set to the calculated address.
334 * @result 0 if *result is valid. Otherwise, *result is undefined and the
335 * address could not be resolved.
337 int elfu_mDynLookupReldynAddrByName(ElfuElf *me, char *name, GElf_Addr *result);
343 * @brief Relocate a section.
344 * @param metarget ELF model containing cloned section.
345 * @param mstarget Cloned section to be relocated.
346 * @param msrt Section in original ELF model,
347 * containing relocation table.
348 * @result 0 if successful.
349 * Anything else indicates an error.
350 * @note This is currently for INTERNAL USE in Reladd ONLY.
352 int elfu_mRelocate(ElfuElf *metarget, ElfuScn *mstarget, ElfuScn *msrt);
358 * @brief Perform a few sanity checks.
359 * @param me Entire ELF model.
360 * @result 0 if successful.
361 * Anything else indicates an error.
363 int elfu_mCheck(ElfuElf *me);
369 * @brief Dump contents of a PHDR to stdout.
370 * @param me Entire ELF model.
371 * @param mp PHDR to dump.
373 void elfu_mDumpPhdr(ElfuElf *me, ElfuPhdr *mp);
376 * @brief Dump details of a section to stdout.
377 * @param me Entire ELF model.
378 * @param ms Section to dump.
380 void elfu_mDumpScn(ElfuElf *me, ElfuScn *ms);
383 * @brief Dump contents of an entire ELF file model to stdout.
384 * @param me Entire ELF model to dump.
386 void elfu_mDumpElf(ElfuElf *me);
392 * @brief Parse an ELF file to a libelfu model via libelf.
393 * @param e libelf handle to source file.
394 * @result NULL if an error occurred, a fresh ElfuElf otherwise.
396 ElfuElf* elfu_mFromElf(Elf *e);
399 * @brief Serialize a libelfu model to an ELF file via libelf.
400 * @param me Entire ELF model.
401 * @param e libelf handle to destination file.
403 void elfu_mToElf(ElfuElf *me, Elf *e);
409 * @brief Inject contents of an object file into an executable.
410 * @param me Destination ELF model.
411 * @param mrel Source ELF model.
412 * @result 0 if successful.
413 * Anything else indicates an error.
415 int elfu_mReladd(ElfuElf *me, const ElfuElf *mrel);
421 * @brief Overwrite a location with an unconditional jump.
422 * @param me Entire ELF model.
423 * @param from Memory address to overwrite at.
424 * @param to Memory address to jump to.
426 void elfu_mDetour(ElfuElf *me, GElf_Addr from, GElf_Addr to);