@@ -159,14 +159,8 @@ getElf(char *path)
159
159
return ebuf ;
160
160
}
161
161
162
- /*
163
- * Find the GOT ptr as defined in RELA/DYNSYM (.rela.dyn) for symbol & hook it.
164
- * .rela.dyn section:
165
- * The address of relocation entries associated solely with the PLT.
166
- * The relocation table's entries have a one-to-one correspondence with the PLT.
167
- */
168
- int
169
- doGotcha (struct link_map * lm , got_list_t * hook , Elf64_Rela * rel , Elf64_Sym * sym , char * str , int rsz , bool attach )
162
+ static int
163
+ setGot (struct link_map * lm , got_list_t * hook , Elf64_Sym * sym , char * str , Elf64_Rela * rel , size_t rsz , bool attach )
170
164
{
171
165
int i , match = -1 ;
172
166
uint64_t prev ;
@@ -252,9 +246,46 @@ doGotcha(struct link_map *lm, got_list_t *hook, Elf64_Rela *rel, Elf64_Sym *sym,
252
246
return match ;
253
247
}
254
248
249
+ /*
250
+ * Find the GOT ptr as defined in RELA/DYNSYM (.rela.dyn) for symbol & hook it.
251
+ * .rela.dyn section:
252
+ * The address of relocation entries associated solely with the PLT.
253
+ * The relocation table's entries have a one-to-one correspondence with the PLT.
254
+ *
255
+ * There are 2 relocation tables potentially used in an Elf object;
256
+ * 1) relocation rel 2) relocation with addends rela
257
+ * When one or the other is defined, no question. Use what is defined.
258
+ * When both rel and rela are defined we need to walk both tables. Some of the symbols we want to
259
+ * match are in rel and others in rela. Therefore, walk both.
260
+ *
261
+ * TODO: we should use a struct for param definition instead of so many passed params.
262
+ */
263
+ int
264
+ doGotcha (struct link_map * lm , got_list_t * hook , Elf64_Sym * sym , char * str , Elf64_Rela * rel , size_t rsz ,
265
+ Elf64_Rela * rela , size_t rasz , bool attach )
266
+ {
267
+ int matchrel = -1 , matchrela = -1 ;
268
+
269
+ if (rel && (rsz > sizeof (Elf64_Rela ))) {
270
+ matchrel = setGot (lm , hook , sym , str , rel , rsz , attach );
271
+ }
272
+
273
+ if (rela && (rasz > sizeof (Elf64_Rela ))) {
274
+ matchrela = setGot (lm , hook , sym , str , rela , rasz , attach );
275
+ }
276
+
277
+ if ((matchrel != -1 ) || (matchrela != -1 )) {
278
+ return 0 ;
279
+ } else {
280
+ return -1 ;
281
+ }
282
+ }
283
+
255
284
// Locate the needed elf entries from a given link map.
285
+ // TODO: we should use a struct for param definition instead of so many passed params.
256
286
int
257
- getElfEntries (struct link_map * lm , Elf64_Rela * * rel , Elf64_Sym * * sym , char * * str , int * rsz )
287
+ getElfEntries (struct link_map * lm , Elf64_Sym * * sym , char * * str ,
288
+ Elf64_Rela * * rel , size_t * rsz , Elf64_Rela * * rela , size_t * rasz )
258
289
{
259
290
Elf64_Dyn * dyn = NULL ;
260
291
char * got = NULL ; // TODO; got is not needed, debug, remove
@@ -274,6 +305,14 @@ getElfEntries(struct link_map *lm, Elf64_Rela **rel, Elf64_Sym **sym, char **str
274
305
} else {
275
306
* str = (char * )(dyn -> d_un .d_ptr + lm -> l_addr );
276
307
}
308
+ } else if (dyn -> d_tag == DT_PLTGOT ) {
309
+ if (osGetPageProt ((uint64_t )dyn -> d_un .d_ptr ) != -1 ) {
310
+ got = (char * )(dyn -> d_un .d_ptr );
311
+ } else {
312
+ got = (char * )(dyn -> d_un .d_ptr + lm -> l_addr );
313
+ }
314
+ appviewLog (CFG_LOG_DEBUG , "%s:%d DT_PLTGOT: 0x%lx" ,
315
+ __FUNCTION__ , __LINE__ , (unsigned long int )got );
277
316
} else if (dyn -> d_tag == DT_JMPREL ) {
278
317
if (osGetPageProt ((uint64_t )dyn -> d_un .d_ptr ) != -1 ) {
279
318
* rel = (Elf64_Rela * )((char * )(dyn -> d_un .d_ptr ));
@@ -282,19 +321,25 @@ getElfEntries(struct link_map *lm, Elf64_Rela **rel, Elf64_Sym **sym, char **str
282
321
}
283
322
} else if (dyn -> d_tag == DT_PLTRELSZ ) {
284
323
* rsz = dyn -> d_un .d_val ;
285
- } else if (dyn -> d_tag == DT_PLTGOT ) {
324
+ } else if (dyn -> d_tag == DT_RELA ) {
325
+ // This is a 'new' tag. Use it if present instead of DT_JMPREL
286
326
if (osGetPageProt ((uint64_t )dyn -> d_un .d_ptr ) != -1 ) {
287
- got = (char * )(dyn -> d_un .d_ptr );
327
+ * rela = (Elf64_Rela * )(( char * )(dyn -> d_un .d_ptr ) );
288
328
} else {
289
- got = (char * )(dyn -> d_un .d_ptr + lm -> l_addr );
329
+ * rela = (Elf64_Rela * )(( char * )(dyn -> d_un .d_ptr + lm -> l_addr ) );
290
330
}
331
+ } else if (dyn -> d_tag == DT_RELASZ ) {
332
+ // This is a 'new' tag. Use it if present instead of DT_PLTRELSZ
333
+ * rasz = dyn -> d_un .d_val ;
291
334
}
292
335
}
293
336
294
- appviewLog (CFG_LOG_TRACE , "%s:%d name: %s dyn %p sym %p rel %p str %p rsz %d got %p laddr 0x%lx\n " ,
295
- __FUNCTION__ , __LINE__ , lm -> l_name , dyn , * sym , * rel , * str , * rsz , got , lm -> l_addr );
337
+ appviewLog (CFG_LOG_DEBUG , "%s:%d name: %s dyn %p sym %p str %p rel %p rsz %ld rela %p rasz %ld got %p laddr 0x%lx" ,
338
+ __FUNCTION__ , __LINE__ , lm -> l_name , dyn , * sym , * str , * rel , * rsz , * rela , * rasz , got , lm -> l_addr );
296
339
297
- if (* sym == NULL || * rel == NULL || (* rsz < sizeof (Elf64_Rela ))) {
340
+ // if we have neither rel or rela then we have no entries
341
+ if ((* sym == NULL ) || (((* rel == NULL ) || (* rsz < sizeof (Elf64_Rela ))) &&
342
+ ((* rela == NULL ) || (* rasz < sizeof (Elf64_Rela ))))) {
298
343
return -1 ;
299
344
}
300
345
0 commit comments