Hosted by the courtesy of  
http://www.webou.net/communaute/Themes/dilbermc/images/lightblue/logo.jpg 
The stars ASAP english francais spanish arab
Durée du voyage intersidéral francais
Résolutions de l'ONU en HTML francais
Bussard Ramjet english francais
DWARF : dwarf2xml english
ELF : libelf examples english
Code presentation : ctoohtml english

Elf sample home

File Index

All Tags

Tags by File

Tags referrers

file: elf_obj_loc.c


  1 /*
  2 * Copyright (C) 2007 Emmanuel AZENCOT All Rights Reserved. *
  3 *
  4 * This program is free software; you can redistribute it and/or modify it
  5 * under the terms of version 2 of the GNU General Public License as
  6 * published by the Free Software Foundation.
  7 *
  8 * The address of the Free Software Foundation is
  9 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
 10 * Boston, MA 02110-1301, USA.
 11 */

 12
 13 /*
 14 * Prepare an elf relocatable object for disassemby (objdump)
 15 *
 16 * 2007-11-14 16:11:49 Emmanuel AZENCOT
 17 *   Creation
 18 * 2008-01-21 15:44:08
 19 *   Fix resolution for data
 20 * Sun Nov 22 20:33:20 CET 2009
 21 *   bug fix in error message \%s\"
 22 *
 23 * build : gcc -Wall -g -o elf_obj_loc -lelf elf_obj_loc.c
 24 * TODO :
 25 *  clean output, have a verbose mode
 26 *  use info file to retreive .rel corresponding section (instead of name)
 27 *  test big endian object
 28 *  test 64 bits object
 29 *  test other processors
 30 *  deal with other ABI
 31 */

 32 #include <string.h>
 33 #include <stdio.h>
 34 #include <stdlib.h>
 35 #include <sysexits.h>
 36 #include <unistd.h>
 37 #include <fcntl.h>
 38 #include <errno.h>
 39
 40 #include <err.h>
 41 #include <gelf.h>
 42
 43 #include </usr/include/asm/byteorder.h>
 44
 45 #define /*X*/ endian_to_target(tgt_is_be, value) ( (sizeof(value) == 4)?\
 46      ((tgt_is_be)?__cpu_to_be32(value):__cpu_to_le32(value)):        \
 47      ((tgt_is_be)?__cpu_to_be64(value):__cpu_to_le64(value)) )

 48
 49
 50 #define /*X*/ errx(code, fmt, args...) { \
 51   fprintf(stderr,#code ": error in file %s at line %d in function %s:", __FILE__,__LINE__,__FUNCTION__); \
 52   fprintf(stderr,fmt "\n", ##args); \
 53   exit(1); \
 54 }

 55 #define /*X*/ merrx(code, fmt, args...) { \
 56   fprintf(stderr,#code ": error in file %s at line %d in function %s:", __FILE__,__LINE__,__FUNCTION__); \
 57   fprintf(stderr,fmt "\n", ##args); \
 58   return -1; \
 59 }

 60 /**
 61 * @memo Find a section given its name
 62 * @doc
 63 *   Look in evry secttion until it find a section name "scn_name"
 64 * @param __elf Elf Handle to search in
 65 * @param scn_name section name
 66 * @return -1 error, 0 not found, section index
 67 */

 68 int /*X*/ melf_scn_by_name(Elf *__elf, char *scn_name) {
 69   size_t shstrndx;
 70   size_t scn_ndx = 0;
 71   Elf_Scn *scn;
 72   GElf_Shdr shdr;
 73   char *name;
 74
 75   if (elf_getshstrndx(__elf, &shstrndx) != 0)
 76      merrx(EX_SOFTWARE, "getshstrndx() failed: %s.", elf_errmsg(-1));
 77
 78   while ((scn = elf_getscn(__elf, scn_ndx)) != NULL) {
 79
 80      if (gelf_getshdr(scn, &shdr) != &shdr)
 81         merrx(EX_SOFTWARE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));
 82
 83      if ((name = elf_strptr(__elf, shstrndx, shdr.sh_name)) == NULL)
 84         merrx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
 85      if ( !strcmp(scn_name, name) )
 86         return scn_ndx;
 87      scn_ndx++;
 88   }
 89   return 0;
 90 }
 91 /**
 92 * @memo Symbol table section adtatation
 93 * @doc
 94 *   As symbol table contains section indexes, there must be changed according to new elf
 95 * section layout
 96 * @param __elf a valid input/output elf handle
 97 * @param conv_tbl a section table conversion (see melf_rel_scn_layout)
 98 * @param len conv_tbl number of entries
 99 * @return -1 error, symbol table section index
100 */

101 int /*X*/ melf_scn_sym_shconv(Elf *__elf, ssize_t *conv_tbl, size_t len) {
102   ssize_t scn_ndx_sym;
103   Elf_Scn *scn_sym;
104   Elf_Data *data_sym;
105   size_t ndx_sym;
106   GElf_Sym sym;
107
108   if ( (scn_ndx_sym = melf_scn_by_name(__elf, ".symtab")) <= 0)
109      merrx(EX_SOFTWARE, "melf_scn_by_name() failed to find section .symtab.");
110
111   if ( (scn_sym = elf_getscn(__elf, scn_ndx_sym)) == NULL)
112      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
113
114   if ( (data_sym = elf_getdata(scn_sym, 0)) == NULL )
115      merrx(EX_SOFTWARE, "elf_getdata() failed: %s.", elf_errmsg(-1));
116
117   ndx_sym = 0;
118   while ( gelf_getsym (data_sym, ndx_sym, &sym) == &sym ) {
119      // if ( sym.st_shndx > SHN_LORESERVE && ++ndx_sym) continue;
120      if ( 0 < (ssize_t) sym.st_shndx && (ssize_t) sym.st_shndx < len) {
121         if ( conv_tbl[sym.st_shndx] == -1 )
122            merrx(EX_SOFTWARE, "Can't convert section (0x%x) for symbol index %d", sym.st_shndx, ndx_sym);
123         sym.st_shndx = conv_tbl[sym.st_shndx];
124         if ( gelf_update_sym (data_sym, ndx_sym, &sym) == 0)
125            merrx(EX_SOFTWARE, "gelf_update_sym() failed: %s.", elf_errmsg(-1));
126      }
127      ++ndx_sym;
128   }
129   if ( elf_flagdata (data_sym, ELF_C_SET, ELF_F_DIRTY) == 0)
130      merrx(EX_SOFTWARE, "elf_flagdata() failed: %s.", elf_errmsg(-1));
131
132   return scn_ndx_sym;
133 }
134 /**
135 * @memo Section content Hexa dump
136 * @ doc
137 *  Output section content in hexadecimal format.
138 *  Section can be given by handle or by name.
139 * @param __elf a valid input elf handle
140 * @param scn a valid scn handle or 0
141 * @param scn_name a section name or 0
142 * @return -1 error, 0 okay
143 */

144 int /*X*/ melf_scn_dump(Elf *__elf, Elf_Scn *scn, char *scn_name) {
145   GElf_Shdr shdr;
146   Elf_Data *data;
147   size_t shstrndx;
148   char *p; int i;
149
150   if ( !scn ) {
151      size_t scn_ndx;
152      if ( !scn_name )
153         merrx(EX_SOFTWARE, "Both name and scn handle are nul");
154      if ( (scn_ndx = melf_scn_by_name(__elf, scn_name)) <= 0)
155         merrx(EX_SOFTWARE, "melf_scn_by_name() failed to find section %s.", scn_name);
156      if ( (scn = elf_getscn(__elf, scn_ndx)) == NULL)
157         merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
158
159   }
160   if (elf_getshstrndx(__elf, &shstrndx) != 0)
161      merrx(EX_SOFTWARE, "getshstrndx() failed: %s.", elf_errmsg(-1));
162
163   if (gelf_getshdr(scn, &shdr) != &shdr)
164      merrx(EX_SOFTWARE, "getshdr(shstrndx) failed: %s.", elf_errmsg(-1));
165   if ((scn_name = elf_strptr(__elf, shstrndx, shdr.sh_name)) == NULL)
166      merrx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
167   if ( (data = elf_getdata(scn, 0)) == NULL )
168      merrx(EX_SOFTWARE, "elf_getdata() failed: %s.", elf_errmsg(-1));
169
170   printf("Dump section %s: size=%jd\n", scn_name, (uintmax_t) shdr.sh_size);
171
172   p = (char *) data->d_buf;
173   for ( i = 0; i < data->d_size; i++ ) {
174      printf("%02hhx ", *p++);
175      if ( !((i + 17) %16) ) printf("\n");
176   }
177   printf("\n");
178   return 0;
179 }
180 /**
181 * @memo Symbol table listing
182 * @doc
183 *   print the symbol table. Symbol strings are taken from the section named
184 * ".strtab". (Usualy, the strings and taken from section index pointed by
185 * sh_link field of section header).
186 * @param __elf valid input elf handle
187 * @return -1 error, symbol table section index
188 */

189 int /*X*/ melf_scn_sym_list(Elf *__elf) {
190   ssize_t scn_ndx_sym, scn_ndx_str;
191   Elf_Scn *scn_sym;
192   Elf_Data *data_sym;
193   GElf_Sym sym;
194   size_t ndx_sym;
195
196   if ( (scn_ndx_sym = melf_scn_by_name(__elf, ".symtab")) <= 0)
197      merrx(EX_SOFTWARE, "melf_scn_by_name() failed to find section .symtab.");
198   /* should use shdr_sym.sh_link ? */
199   if ( (scn_ndx_str = melf_scn_by_name(__elf, ".strtab")) <= 0)
200      merrx(EX_SOFTWARE, "melf_scn_by_name() failed to find section .symtab.");
201
202   if ( (scn_sym = elf_getscn(__elf, scn_ndx_sym)) == NULL)
203      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
204
205   if ( (data_sym = elf_getdata(scn_sym, 0)) == NULL )
206      merrx(EX_SOFTWARE, "elf_getdata() failed: %s.", elf_errmsg(-1));
207
208   /* walk throught symbols table */
209   printf("name   value   size   info   other shndx\n");
210   ndx_sym = 0;
211   while ( gelf_getsym (data_sym, ndx_sym, &sym) == &sym ) {
212      char *name;
213      if ((name = elf_strptr(__elf, scn_ndx_str, sym.st_name)) == NULL)
214         merrx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
215
216      printf("%05x %08llx %04llx %08x %05x %04x %s\n",
217             sym.st_name, sym.st_value, sym.st_size, sym.st_info, sym.st_other, sym.st_shndx, name);
218      ++ndx_sym;
219   }
220
221   return scn_ndx_sym;
222 }
223
224 /**
225 * @memo Symbol table locatioon adtatation
226 * @doc
227 *   Produce a trivial memory mapping for the alloc sections. Change sections adresses
228 * according to it.
229 *   Give all UNDEF symbol a recognisable location and change value in symbol table.
230 * @param __elf a valid input/output elf handle
231 * @return -1 error, symbol table section index
232 */

233 int /*X*/ melf_scn_sym_lnk(Elf *__elf) {
234   ssize_t scn_ndx_sym, scn_ndx;
235   Elf_Scn *scn_sym, *scn;
236   GElf_Shdr shdr;
237   Elf_Data *data_sym;
238   Elf64_Addr PC = 0x08048000;
239   size_t ndx_sym;
240   GElf_Sym sym;
241
242
243   if ( (scn_ndx_sym = melf_scn_by_name(__elf, ".symtab")) <= 0)
244      merrx(EX_SOFTWARE, "melf_scn_by_name() failed to find section .symtab.");
245   if ( (scn_sym = elf_getscn(__elf, scn_ndx_sym)) == NULL)
246      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
247
248   if ( (data_sym = elf_getdata(scn_sym, 0)) == NULL )
249      merrx(EX_SOFTWARE, "elf_getdata() failed: %s.", elf_errmsg(-1));
250
251   /* Map alloc sectionq in memory */
252   for ( scn = 0; (scn = elf_nextscn(__elf, scn)) != NULL; ) {
253      scn_ndx = elf_ndxscn (scn);
254
255      if (gelf_getshdr(scn, &shdr) != &shdr)
256         merrx(EX_SOFTWARE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));
257      if ( !(shdr.sh_flags & SHF_ALLOC) && ++scn_ndx )
258         continue;
259
260      shdr.sh_addr = PC;
261      if ( shdr.sh_addralign )
262         PC += ((shdr.sh_size + shdr.sh_addralign-1)/shdr.sh_addralign)*shdr.sh_addralign;
263      else
264         PC += shdr.sh_size;
265      if ( elf_flagshdr (scn, ELF_C_SET, ELF_F_DIRTY) == 0)
266         merrx(EX_SOFTWARE, "elf_flagshdr() failed: %s.", elf_errmsg(-1));
267      if ( gelf_update_shdr (scn, &shdr) == 0)
268         merrx(EX_SOFTWARE, "gelf_update_shdr() failed: %s.", elf_errmsg(-1));
269   }
270   /* give UNDEF a decent location */
271   PC = 0x02500000;
272   ndx_sym = 0;
273   while ( gelf_getsym (data_sym, ndx_sym, &sym) == &sym ) {
274      if ( sym.st_shndx != 0 && ++ndx_sym) continue;
275      sym.st_value = PC;
276      sym.st_shndx = SHN_ABS;
277      PC += 0x10;
278      if ( gelf_update_sym (data_sym, ndx_sym, &sym) == 0)
279         merrx(EX_SOFTWARE, "gelf_update_sym() failed: %s.", elf_errmsg(-1));
280
281      ++ndx_sym;
282   }
283   if ( elf_flagdata (data_sym, ELF_C_SET, ELF_F_DIRTY) == 0)
284      merrx(EX_SOFTWARE, "elf_flagdata() failed: %s.", elf_errmsg(-1));
285
286   return scn_ndx_sym;
287 }
288 /**
289 * @memo target data encoding
290 * 0 little endian
291 * 1 big endian
292 */

293 int /*X*/ target_is_big_endian;
294 /**
295 * @memo Relocate section
296 * @doc
297 *   Apply the relocations contained in .rel section to a section.
298 * Note : Symbole table section .symtab must have adapted prior.
299 * @param elf Elf handler for section beeing relocated
300 * @param scn_ndx_out Section index to relocate
301 * @param scn_ndx_rel Reloc section index
302 * @param scn_ndx_sym Symbol table section
303 * @return -1 on error, 0 else
304 */

305 int /*X*/ melf_scn_rel(Elf *elf_out, size_t scn_ndx_out,
306                 Elf *elf_rel, size_t scn_ndx_rel,
307                 Elf *elf_sym, size_t scn_ndx_sym) {
308   Elf_Scn *scn_out, *scn_rel, *scn_sym;
309   GElf_Shdr shdr_out, shdr_rel, shdr_sym;
310   Elf_Data *data_out, *data_rel, *data_sym;
311   int rel_i;
312
313   printf("index out : %d, rel : %d, sym : %d", scn_ndx_out, scn_ndx_rel, scn_ndx_sym);
314
315   if ( (scn_rel = elf_getscn(elf_rel, scn_ndx_rel)) == NULL)
316      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
317   if ( (scn_out = elf_getscn(elf_out, scn_ndx_out)) == NULL)
318      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
319   if ( (scn_sym = elf_getscn(elf_sym, scn_ndx_sym)) == NULL)
320      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
321
322   if (gelf_getshdr(scn_rel, &shdr_rel) != &shdr_rel)
323      merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
324   if (gelf_getshdr(scn_out, &shdr_out) != &shdr_out)
325      merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
326   if (gelf_getshdr(scn_sym, &shdr_sym) != &shdr_sym)
327      merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
328
329   if ( (data_out = elf_getdata(scn_out, 0)) == NULL)
330      merrx(EX_SOFTWARE, "getdata() failed: %s.", elf_errmsg(-1));
331   if ( shdr_out.sh_size != data_out->d_size )
332      fprintf(stderr, "warning tgt data containt more than one chunk\n");
333
334   if ( (data_rel = elf_getdata(scn_rel, 0)) == NULL)
335      merrx(EX_SOFTWARE, "getdata() failed: %s.", elf_errmsg(-1));
336   if ( shdr_rel.sh_size != data_rel->d_size )
337      fprintf(stderr, "warning rel data is in more than one chunk\n");
338
339   if ( (data_sym = elf_getdata(scn_sym, 0)) == NULL)
340      merrx(EX_SOFTWARE, "getdata() failed: %s.", elf_errmsg(-1));
341   if ( shdr_sym.sh_size != data_sym->d_size )
342      fprintf(stderr, "warning tgt data containt more than one chunk\n");
343
344   for (rel_i = 0; ; rel_i++ ) {
345      GElf_Rel rel;
346      GElf_Sym sym;
347      Elf_Scn *scn_dst;
348      GElf_Shdr shdr_dst;
349      Elf64_Addr shaddr = 0;
350     
351      if ( gelf_getrel (data_rel, rel_i, &rel) != &rel )
352         break;
353      
354      if ( gelf_getsym (data_sym, GELF_R_SYM(rel.r_info), &sym) != &sym )
355         merrx(EX_SOFTWARE, "gelf_getsym() failed: %s. Symbol %lld not found", elf_errmsg(-1), GELF_R_SYM(rel.r_info));
356
357      if ( sym.st_shndx < SHN_LORESERVE ) {
358         if ( (scn_dst = elf_getscn(elf_out, sym.st_shndx)) == NULL)
359            merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
360         if (gelf_getshdr(scn_dst, &shdr_dst) != &shdr_dst)
361            merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
362         shaddr = shdr_dst.sh_addr;
363      }
364      switch (GELF_R_TYPE(rel.r_info)) {
365      case R_386_32:
366         *((uint32_t *)(((char *)data_out->d_buf) + rel.r_offset)) +=
367                          endian_to_target(target_is_big_endian,(uint32_t)(sym.st_value +  shaddr));
368         break;
369      case R_386_PC32: {
370
371         *((uint32_t *)(((char *)data_out->d_buf) + rel.r_offset)) =
372                          endian_to_target(target_is_big_endian,(uint32_t)(sym.st_value + shaddr - (shdr_out.sh_addr + rel.r_offset) - 4));
373         break;
374      }
375      default:
376         merrx(EX_SOFTWARE, "Can you help me to about this type of reloc (%lld) ? Oh I would do much you tacke care of this ... please ...\n", GELF_R_TYPE(rel.r_info));
377      }
378   }
379   if ( elf_flagdata (data_out, ELF_C_SET, ELF_F_DIRTY) == 0)
380      merrx(EX_SOFTWARE, "elf_flagdata() failed: %s.", elf_errmsg(-1));
381
382   if ( gelf_update_shdr (scn_out, &shdr_out) == 0)
383      errx(EX_SOFTWARE, "gelf_update_shdr() failed: %s.", elf_errmsg(-1));
384   // printf("@%d ELF error %s\n", __LINE__, elf_errmsg(-1));
385   return 0;
386 }
387 /**
388 * @memo Build output section table
389 * @doc
390 *   The table is indexed by input section indexes. For each of them, the value
391 * can be (-1) not used or the output section.
392 * @param __elf valid input elf handle
393 * @param conv_tbl an array of at least the number of section in __elf
394 * @return -1 on error, number of sections in output.
395 */

396 int /*X*/ melf_rel_scn_layout(Elf *__elf, ssize_t *conv_tbl) {
397   GElf_Ehdr ehdr;
398   GElf_Shdr shdr;
399   Elf_Scn *scn;
400   size_t ndx_out = 1;
401
402   if (gelf_getehdr(__elf, &ehdr) != &ehdr)
403      errx(EX_SOFTWARE, "gelf_getehdr() failed: %s.", elf_errmsg(-1));
404
405   conv_tbl[0] = 0;
406   /* set allocable sections first */
407   for ( scn = 0; (scn = elf_nextscn(__elf, scn)) != NULL; ) {
408      conv_tbl[elf_ndxscn (scn)] = -1;
409      if (gelf_getshdr(scn, &shdr) != &shdr)
410         merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
411      if ( shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) continue;
412      if ( !(shdr.sh_flags & SHF_ALLOC) ) continue;
413      conv_tbl[elf_ndxscn (scn)] = ndx_out++;
414   }
415   for ( scn = 0; (scn = elf_nextscn(__elf, scn)) != NULL; ) {
416      if (gelf_getshdr(scn, &shdr) != &shdr)
417         merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
418      if ( shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) continue;
419      if ( (shdr.sh_flags & SHF_ALLOC) ) continue;
420      conv_tbl[elf_ndxscn (scn)] = ndx_out++;
421   }
422   for ( scn = 0; (scn = elf_nextscn(__elf, scn)) != NULL; ) {
423      printf ( "section transfert table[%2d] = %2d\n", elf_ndxscn (scn), conv_tbl[elf_ndxscn (scn)]);
424   }
425   return ndx_out;
426 }
427 /**
428 * @memo Find .rel section correspondind to a section
429 * @doc
430 *   Get peer section .rel that correspond to a section. The criteria to find peer is
431 * done througth the section name.
432 *  Should use sh_link and sh_info instead.
433 * @param elf Elf handler
434 * @param scn_ndx Section index
435 * @return -1 on error, 0 not find, or scn index
436 */

437 int /*X*/ melf_find_rel_section(Elf *__elf, size_t scn_ndx) {
438   size_t shstrndx;
439   Elf_Scn *scn, *scn_r;
440   GElf_Shdr shdr, shdr_r;
441   char *scn_name, *scn_name_r;
442
443   if (elf_getshstrndx(__elf, &shstrndx) != 0)
444      merrx(EX_SOFTWARE, "getshstrndx() failed: %s.", elf_errmsg(-1));
445   if ( (scn = elf_getscn(__elf, scn_ndx)) == NULL)
446      merrx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
447   if (gelf_getshdr(scn, &shdr) != &shdr)
448      merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
449   if ((scn_name = elf_strptr(__elf, shstrndx, shdr.sh_name)) == NULL)
450      merrx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
451
452   for ( scn_r = 0; (scn_r = elf_nextscn(__elf, scn_r)) != NULL; ) {
453
454      if ( gelf_getshdr(scn_r, &shdr_r) != &shdr_r)
455         merrx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
456
457      if ( shdr_r.sh_type != SHT_REL && shdr_r.sh_type != SHT_RELA) continue;
458
459      if ((scn_name_r = elf_strptr(__elf, shstrndx, shdr_r.sh_name)) == NULL)
460         merrx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
461      if ( memcmp(scn_name_r, ".rel", 4) ) continue;
462      if ( strcmp(scn_name_r + 4, scn_name) ) continue;
463      return elf_ndxscn (scn_r);
464   }
465
466   return 0;
467 }
468 int /*X*/ melf_is_scn_reloc(Elf_Scn  *scn) {
469   GElf_Shdr shdr;
470
471   if (gelf_getshdr(scn, &shdr) != &shdr)
472      errx(EX_SOFTWARE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));
473
474   if ( shdr.sh_type == SHT_REL || shdr.sh_type == SHT_RELA) {
475      return 1;
476   } else {
477      return 0;
478   }
479   return -1;
480 }
481 /**
482 * @memo Prepare an elf from relocatable object for disassemble
483 * @doc
484 *  binutils objdump disassemble does not give a correct output for relocatable
485 * object, mainly because it does not apply relocation section indications to
486 * the corresponding section.
487 * This tool handle this relocation.
488 */

489 int /*X*/ main(int argc, char *argv[]) {
490   int fd_in = -1, fd_out = -1;
491   Elf *elf_in = 0, *elf_out = 0;
492
493   Elf_Scn  *scn_in, *scn_out;
494   Elf_Data *data_in, *data_out;
495   GElf_Ehdr ehdr_in, ehdr_out;
496
497   GElf_Shdr shdr_in, shdr_out;
498   size_t n, shstrndx;
499
500   ssize_t *v_scn_in_2_out;
501   char **sh_names;
502
503   int scn_ndx_sym, scn_ndx_out = 0, scn_ndx_in;
504
505   if (argc != 3)
506      errx(EX_USAGE, "USAGE: %s in-file-name out-file-name", argv[0]);
507
508   if (elf_version(EV_CURRENT) == EV_NONE)
509      errx(EX_SOFTWARE, "ELF library initialization failed: %s", elf_errmsg(-1));
510
511   /* Elf input setup */
512   if ((fd_in = open(argv[1], O_RDONLY, 0)) < 0)
513      err(EX_NOINPUT, "open \"%s\" failed", argv[1]);
514
515   if ((elf_in = elf_begin(fd_in, ELF_C_READ, NULL)) == NULL)
516      errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
517
518   if (gelf_getehdr(elf_in, &ehdr_in) != &ehdr_in)
519      errx(EX_SOFTWARE, "gelf_getehdr() failed: %s.", elf_errmsg(-1));
520
521   /* Checks and warns */
522   if ( elf_kind(elf_in) != ELF_K_ELF || ehdr_in.e_type != ET_REL) {
523      fprintf(stderr, "%s : %s must be an elf relocatable object\n", argv[0], argv[1]);
524      exit(1);
525   }
526   if ( ehdr_in.e_ident[EI_OSABI] != ELFOSABI_LINUX ) {
527      fprintf(stderr, "%s warning : target OS not implemented\n", argv[0]);
528   }
529   switch ( ehdr_in.e_ident[EI_DATA] ) {
530   case ELFDATA2LSB:
531      target_is_big_endian = 0;
532      break;
533   case ELFDATA2MSB:
534      fprintf(stderr, "%s warning : big endian data encoding is not tested\n", argv[0]);
535      target_is_big_endian = 1;
536      break;
537   default :
538      fprintf(stderr, "%s : unsupported data type (%d)\n", argv[0], ehdr_in.e_ident[EI_DATA]);
539      break;
540   }
541   if ( ehdr_in.e_machine != EM_386 ) {
542      fprintf(stderr, "%s warning : machine not implemented\n", argv[0]);
543   }
544
545   printf("ELF %s contains %d sections\n", argv[1], ehdr_in.e_shnum);
546
547   if (!(sh_names = (char **)malloc(ehdr_in.e_shnum*sizeof(char *))))
548      errx(EX_SOFTWARE, "malloc \"%s\" failed", strerror(errno));
549
550   if (elf_getshstrndx(elf_in, &shstrndx) != 0)
551       errx(EX_SOFTWARE, "getshstrndx() failed: %s, %d.", elf_errmsg(-1), shstrndx);
552
553   for ( scn_ndx_in = 0; scn_ndx_in < ehdr_in.e_shnum; scn_ndx_in++ ) {
554      if ((scn_in = elf_getscn(elf_in, scn_ndx_in)) == NULL)
555         errx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
556
557      if (gelf_getshdr(scn_in, &shdr_in) != &shdr_in)
558         errx(EX_SOFTWARE, "getshdr() failed: %s.", elf_errmsg(-1));
559
560      if ((sh_names[scn_ndx_in] = elf_strptr(elf_in, shstrndx, shdr_in.sh_name)) == NULL)
561         errx(EX_SOFTWARE, "elf_strptr() failed: %s.", elf_errmsg(-1));
562   }
563
564 //   if ((fd_out = open(argv[2], O_WRONLY|O_CREAT, 0777)) < 0)
565   if ((fd_out = open(argv[2], O_RDWR|O_CREAT, 0777)) < 0)
566      errx(EX_OSERR, "open \"%s\" failed", argv[2]);
567
568   if ((elf_out = elf_begin(fd_out, ELF_C_WRITE, NULL)) == NULL)
569 //   if ((elf_out = elf_begin(fd_out, ELF_C_RDWR, NULL)) == NULL)
570      errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
571
572   /* Create and set new Elf header */
573   if ( gelf_newehdr(elf_out, ehdr_in.e_ident[EI_CLASS]) == 0)
574      errx(EX_SOFTWARE, "gelf_newehdr() failed: %s.", elf_errmsg(-1));
575
576   if ( gelf_getehdr(elf_out, &ehdr_out) != &ehdr_out)
577      errx(EX_SOFTWARE, "gelf_getehdr() failed: %s.", elf_errmsg(-1));
578    ehdr_out = ehdr_in;
579    if ( gelf_update_ehdr (elf_out, &ehdr_out) == 0)
580      errx(EX_SOFTWARE, "gelf_update_ehdr() failed: %s.", elf_errmsg(-1));
581
582   /* Build section layout table */
583   if (!(v_scn_in_2_out = (ssize_t *)malloc(ehdr_in.e_shnum * sizeof(ssize_t))))
584      errx(EX_SOFTWARE, "malloc \"%s\" failed", strerror(errno));
585   v_scn_in_2_out[0] = 0;
586   if ( (ssize_t)(scn_ndx_out = melf_rel_scn_layout(elf_in, v_scn_in_2_out)) < 0 )
587      errx(EX_SOFTWARE, "melf_rel_scn_layout() failed.");
588   ehdr_out.e_shnum = scn_ndx_out;
589
590   /* copy all sections to new elf execpt rel.section followin v_scn_in2_out layout */
591   printf("Copy section to new elf : ");
592   for ( scn_ndx_out = 1; scn_ndx_out < ehdr_out.e_shnum; scn_ndx_out++ ) {
593
594      /* get source section corresponding to scn_ndx_out in layout */
595      for ( scn_ndx_in = 0; scn_ndx_in < ehdr_in.e_shnum; scn_ndx_in++) {
596         if ( scn_ndx_out == v_scn_in_2_out[scn_ndx_in] ) goto found_scn_source;
597      }
598      continue;
599      found_scn_source:
600
601      /* Recognize and set section names string table index */
602      if ( shstrndx == scn_ndx_in ) ehdr_out.e_shstrndx = scn_ndx_out;
603
604      if ((scn_in = elf_getscn(elf_in, scn_ndx_in)) == NULL)
605         errx(EX_SOFTWARE, "getscn() failed: %s.", elf_errmsg(-1));
606
607      /* copy section to new elf */
608      if (gelf_getshdr(scn_in, &shdr_in) != &shdr_in)
609         errx(EX_SOFTWARE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));
610
611      if ((scn_out = elf_newscn(elf_out)) == NULL)
612         errx(EX_SOFTWARE, "elf_newscn() failed: %s.", elf_errmsg(-1));
613      data_in = NULL; n = 0;
614      while (n < shdr_in.sh_size && (data_in = elf_getdata(scn_in, data_in)) != NULL) {
615         if ((data_out = elf_newdata(scn_out)) == NULL)
616            errx(EX_SOFTWARE, "elf_newdata() failed: %s.", elf_errmsg(-1));
617         *data_out = *data_in;
618         n +=  data_in->d_size;
619      }
620
621      if ( gelf_getshdr(scn_out, &shdr_out) != &shdr_out)
622         errx(EX_SOFTWARE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));
623
624      shdr_out = shdr_in;
625      /* convert link to new section numbering */
626      if ( shdr_in.sh_link )
627         shdr_out.sh_link = v_scn_in_2_out[shdr_in.sh_link];
628      
629      if ( gelf_update_shdr (scn_out, &shdr_out) == 0)
630         errx(EX_SOFTWARE, "gelf_update_shdr() failed: %s.", elf_errmsg(-1));
631
632      printf("%d<%d ", scn_ndx_out, scn_ndx_in);
633   }
634   printf("done\n");
635
636   /* update ehdr to record e_shstrndx */
637    if ( gelf_update_ehdr (elf_out, &ehdr_out) == 0)
638      errx(EX_SOFTWARE, "gelf_update_ehdr() failed: %s.", elf_errmsg(-1));
639
640   if (elf_update(elf_out, ELF_C_WRITE) < 0)
641      errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1));
642
643   elf_end(elf_out);
644   /*
645    * I did not found an other way to modify section in out elf
646    * other than to reopen it in read/write mode
647    */

648   if ((elf_out = elf_begin(fd_out, ELF_C_RDWR, NULL)) == NULL)
649      errx(EX_SOFTWARE, "elf_begin() failed: %s.", elf_errmsg(-1));
650
651    if ( melf_scn_sym_shconv(elf_out, v_scn_in_2_out, ehdr_in.e_shnum) < 0)
652      errx(EX_SOFTWARE, "melf_scn_sym_shconv failled");
653   if (elf_update(elf_out, ELF_C_NULL) < 0)
654      errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1));
655
656   /* Adapt symbol table */
657   if ( (scn_ndx_sym = melf_scn_sym_lnk(elf_out)) < 0)
658      errx(EX_SOFTWARE, "melf_scn_sym_lnk() failed");
659   if (elf_update(elf_out, ELF_C_NULL) < 0)
660      errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1));
661
662 //     if (melf_scn_sym_list(elf_out) < 0 ) exit(1);
663 //     if (melf_scn_dump(elf_out, 0, ".symtab") <0 ) exit(1);
664 //     if (melf_scn_dump(elf_out, 0, ".shstrtab") <0 ) exit(1);
665
666   /* peer section and rel.section */
667   for ( scn_ndx_out = 1; scn_ndx_out < ehdr_out.e_shnum; scn_ndx_out++ ) {
668      ssize_t scn_rel_i;
669      /* skip .rel<.sections> */
670      for ( scn_ndx_in = 0; scn_ndx_in < ehdr_in.e_shnum; scn_ndx_in++) {
671         if ( scn_ndx_out == v_scn_in_2_out[scn_ndx_in] ) goto found_scn_source_2;
672      }
673      continue;
674      found_scn_source_2:
675
676      /* track section count for section names string table index */
677      printf("[%d] : %s", scn_ndx_in, sh_names[scn_ndx_in]);
678      switch ( (scn_rel_i = melf_find_rel_section(elf_in, scn_ndx_in)) ) {
679      case -1: errx(EX_SOFTWARE, "melf_find_rel_section() failed"); break;
680      case  0: break;
681      default :
682         /* Locate section if there is a .rel for it */
683         printf(" linked with section : [%d]", scn_rel_i);
684         if ( melf_scn_rel(elf_out, scn_ndx_out, elf_in, scn_rel_i, elf_out, scn_ndx_sym) < 0 )
685            errx(EX_SOFTWARE, "melf_scn_reloc() failed");
686      }          
687      printf("\n");
688   }
689
690 /*
691   if (elf_update(elf_out, ELF_C_NULL) < 0)
692      errx(EX_SOFTWARE, "elf_update(NULL) failed: %s.", elf_errmsg(-1));
693 */

694   if (elf_update(elf_out, ELF_C_WRITE) < 0)
695      errx(EX_SOFTWARE, "elf_update() failed: %s.", elf_errmsg(-1));
696
697   if ( elf_out ) elf_end(elf_out);
698   if ( fd_out >= 0 ) close(fd_out);
699   if ( elf_in ) elf_end(elf_in);
700   if ( fd_in >= 0 ) close(fd_in);
701
702
703   exit(EX_OK);
704 }
705


Elf sample home

File Index

All Tags

Tags by File

Tags referrers

C to HTML Conversion by ctoohtml

Hosted by the courtesy of  
http://www.webou.net/communaute/Themes/dilbermc/images/lightblue/logo.jpg 
The stars ASAP english francais spanish
Durée du voyage intersidéral francais
Résolutions de l'ONU en HTML francais
Bussard Ramjet english francais
DWARF : dwarf2xml english
ELF : libelf examples english
Code presentation : ctoohtml english