Hosted by the courtesy of  
 GitHub 
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  
 GitHub 
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