Home | History | Annotate | Download | only in tests
      1 /* Test program for elf_newdata function.
      2    Copyright (C) 2015 Red Hat, Inc.
      3    This file is part of elfutils.
      4 
      5    This file is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    elfutils is distributed in the hope that it will be useful, but
     11    WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17 
     18 #ifdef HAVE_CONFIG_H
     19 # include <config.h>
     20 #endif
     21 
     22 #include <errno.h>
     23 #include <fcntl.h>
     24 #include <inttypes.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <string.h>
     28 #include <unistd.h>
     29 
     30 #include ELFUTILS_HEADER(elf)
     31 #include <gelf.h>
     32 
     33 // Random data string (16 bytes).
     34 static char *DATA = "123456789ABCDEF";
     35 static size_t DATA_LEN = 16;
     36 
     37 static void
     38 add_section_data (Elf *elf, char *buf, size_t len)
     39 {
     40   printf ("Adding %zd bytes.\n", len);
     41 
     42   Elf_Scn *scn = elf_getscn (elf, 1);
     43   if (scn == NULL)
     44     {
     45       printf ("couldn't get data section: %s\n", elf_errmsg (-1));
     46       exit (1);
     47     }
     48 
     49   Elf_Data *data = elf_newdata (scn);
     50   if (data == NULL)
     51     {
     52       printf ("cannot create newdata for section: %s\n", elf_errmsg (-1));
     53       exit (1);
     54     }
     55 
     56   data->d_buf = buf;
     57   data->d_type = ELF_T_BYTE;
     58   data->d_size = len;
     59   data->d_align = 1;
     60   data->d_version = EV_CURRENT;
     61 
     62   // Let the library compute the internal structure information.
     63   if (elf_update (elf, ELF_C_NULL) < 0)
     64     {
     65       printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
     66       exit (1);
     67     }
     68 
     69 }
     70 
     71 static Elf *
     72 create_elf (int fd, int class, int use_mmap)
     73 {
     74   Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
     75   if (elf == NULL)
     76     {
     77       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
     78       exit (1);
     79     }
     80 
     81   // Create an ELF header.
     82   if (gelf_newehdr (elf, class) == 0)
     83     {
     84       printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
     85       exit (1);
     86     }
     87 
     88   GElf_Ehdr ehdr_mem;
     89   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
     90   if (ehdr == NULL)
     91     {
     92       printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
     93       exit (1);
     94     }
     95 
     96   // Initialize header.
     97   ehdr->e_ident[EI_DATA] = class == ELFCLASS32 ? ELFDATA2LSB : ELFDATA2MSB;
     98   ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
     99   ehdr->e_type = ET_NONE;
    100   ehdr->e_machine = class == ELFCLASS32 ? EM_PPC : EM_X86_64;
    101   ehdr->e_version = EV_CURRENT;
    102 
    103   // Update the ELF header.
    104   if (gelf_update_ehdr (elf, ehdr) == 0)
    105     {
    106       printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
    107       exit (1);
    108     }
    109 
    110   // Create a section.
    111   Elf_Scn *scn = elf_newscn (elf);
    112   if (scn == NULL)
    113     {
    114       printf ("cannot create new section: %s\n", elf_errmsg (-1));
    115       exit (1);
    116     }
    117 
    118   GElf_Shdr shdr_mem;
    119   GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    120   if (shdr == NULL)
    121     {
    122       printf ("cannot get header for data section: %s\n", elf_errmsg (-1));
    123       exit (1);
    124     }
    125 
    126   shdr->sh_type = SHT_PROGBITS;
    127   shdr->sh_flags = 0;
    128   shdr->sh_addr = 0;
    129   shdr->sh_link = SHN_UNDEF;
    130   shdr->sh_info = SHN_UNDEF;
    131   shdr->sh_addralign = 1;
    132   shdr->sh_entsize = 1;
    133   shdr->sh_name = 0;
    134 
    135   // Finish section, update the header.
    136   if (gelf_update_shdr (scn, shdr) == 0)
    137     {
    138       printf ("cannot update header for DATA section: %s\n", elf_errmsg (-1));
    139       exit (1);
    140     }
    141 
    142   // Add some data to the section.
    143   add_section_data (elf, DATA, DATA_LEN);
    144 
    145   // Write everything to disk.
    146   if (elf_update (elf, ELF_C_WRITE) < 0)
    147     {
    148       printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
    149       exit (1);
    150     }
    151 
    152   return elf;
    153 }
    154 
    155 static Elf *
    156 read_elf (int fd, int use_mmap)
    157 {
    158   printf ("Reading ELF file\n");
    159   Elf *elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
    160   if (elf == NULL)
    161     {
    162       printf ("cannot create ELF descriptor read-again: %s\n", elf_errmsg (-1));
    163       exit (1);
    164     }
    165 
    166   return elf;
    167 }
    168 
    169 static void
    170 check_section_size (Elf *elf, size_t size)
    171 {
    172   Elf_Scn *scn = elf_getscn (elf, 1);
    173   if (scn == NULL)
    174     {
    175       printf ("couldn't get data section: %s\n", elf_errmsg (-1));
    176       exit (1);
    177     }
    178 
    179   GElf_Shdr shdr_mem;
    180   GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
    181   if (shdr == NULL)
    182     {
    183       printf ("cannot get header for DATA section: %s\n", elf_errmsg (-1));
    184       exit (1);
    185     }
    186 
    187   if (shdr->sh_size == size)
    188     printf ("OK %zd bytes.\n", size);
    189   else
    190     {
    191       printf ("BAD size, expected %zd, got %" PRIu64 "\n",
    192 	      size, shdr->sh_size);
    193       exit (-1);
    194     }
    195 }
    196 
    197 static void
    198 check_section_data (Elf *elf, char *data, size_t len, size_t times)
    199 {
    200   Elf_Scn *scn = elf_getscn (elf, 1);
    201   if (scn == NULL)
    202     {
    203       printf ("couldn't get data section: %s\n", elf_errmsg (-1));
    204       exit (1);
    205     }
    206 
    207   Elf_Data *d = NULL;
    208   for (size_t i = 0; i < times; i++)
    209     {
    210       if (d == NULL || i * len >= d->d_off + d->d_size)
    211 	{
    212 	  d = elf_getdata (scn, d);
    213 	  if (d == NULL)
    214 	    {
    215 	      printf ("cannot get data for section item %zd: %s\n",
    216 		      i, elf_errmsg (-1));
    217 	      exit (1);
    218 	    }
    219 	  else
    220 	    printf ("OK, section data item %zd (d_off: %" PRId64
    221 		    ", d_size: %zd)\n", i, d->d_off, d->d_size);
    222 	}
    223       char *d_data = (char *) d->d_buf + (len * i) - d->d_off;
    224       printf ("%zd data (d_off: %" PRId64
    225 	      ", len * i: %zd): (%p + %" PRId64 ") %s\n",
    226 	      i, d->d_off, len * i, d->d_buf, (len * i) - d->d_off, d_data);
    227       if (memcmp (data, d_data, len) != 0)
    228 	{
    229 	  printf ("Got bad data in section for item %zd.\n", i);
    230 	  exit (1);
    231 	}
    232     }
    233 }
    234 
    235 static void
    236 check_elf (int class, int use_mmap)
    237 {
    238   static const char *fname;
    239   if (class == ELFCLASS32)
    240     fname = use_mmap ? "newdata.elf32.mmap" : "newdata.elf32";
    241   else
    242     fname = use_mmap ? "newdata.elf64.mmap" : "newdata.elf64";
    243 
    244   printf ("\ncheck_elf: %s\n", fname);
    245 
    246   int fd = open (fname, O_RDWR|O_CREAT|O_TRUNC, 00666);
    247   if (fd == -1)
    248     {
    249       printf ("cannot create `%s': %s\n", fname, strerror (errno));
    250       exit (1);
    251     }
    252 
    253   Elf *elf = create_elf (fd, class, use_mmap);
    254   check_section_size (elf, DATA_LEN);
    255   check_section_data (elf, DATA, DATA_LEN, 1);
    256 
    257   // Add some more data (won't be written to disk).
    258   add_section_data (elf, DATA, DATA_LEN);
    259   check_section_size (elf, 2 * DATA_LEN);
    260   check_section_data (elf, DATA, DATA_LEN, 2);
    261 
    262   if (elf_end (elf) != 0)
    263     {
    264       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
    265       exit (1);
    266     }
    267 
    268   close (fd);
    269 
    270   // Read the ELF from disk now.  And add new data directly.
    271   fd = open (fname, O_RDONLY);
    272   if (fd == -1)
    273     {
    274       printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
    275       exit (1);
    276     }
    277 
    278   elf = read_elf (fd, use_mmap);
    279   check_section_size (elf, DATA_LEN);
    280   // But don't check contents, that would read the data...
    281 
    282   // Add some more data.
    283   add_section_data (elf, DATA, DATA_LEN);
    284   check_section_size (elf, 2 * DATA_LEN);
    285   check_section_data (elf, DATA, DATA_LEN, 2);
    286 
    287   // And some more.
    288   add_section_data (elf, DATA, DATA_LEN);
    289   check_section_size (elf, 3 * DATA_LEN);
    290   check_section_data (elf, DATA, DATA_LEN, 3);
    291 
    292   if (elf_end (elf) != 0)
    293     {
    294       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
    295       exit (1);
    296     }
    297 
    298   close (fd);
    299 
    300   // Read the ELF from disk now.  And add new data after raw reading.
    301   fd = open (fname, O_RDONLY);
    302   if (fd == -1)
    303     {
    304       printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
    305       exit (1);
    306     }
    307 
    308   elf = read_elf (fd, use_mmap);
    309   check_section_size (elf, DATA_LEN);
    310   // But don't check contents, that would read the data...
    311 
    312   // Get raw data before adding new data.
    313   Elf_Scn *scn = elf_getscn (elf, 1);
    314   if (scn == NULL)
    315     {
    316       printf ("couldn't get data section: %s\n", elf_errmsg (-1));
    317       exit (1);
    318     }
    319 
    320   printf ("elf_rawdata\n");
    321   Elf_Data *data = elf_rawdata (scn, NULL);
    322   if (data == NULL)
    323     {
    324       printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
    325       exit (1);
    326     }
    327 
    328   if (data->d_size != DATA_LEN)
    329     {
    330       printf ("Unexpected Elf_Data: %zd", data->d_size);
    331       exit (1);
    332     }
    333 
    334   // Now add more data.
    335   add_section_data (elf, DATA, DATA_LEN);
    336   check_section_size (elf, 2 * DATA_LEN);
    337   check_section_data (elf, DATA, DATA_LEN, 2);
    338 
    339   // And some more.
    340   add_section_data (elf, DATA, DATA_LEN);
    341   check_section_size (elf, 3 * DATA_LEN);
    342   check_section_data (elf, DATA, DATA_LEN, 3);
    343 
    344   if (elf_end (elf) != 0)
    345     {
    346       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
    347       exit (1);
    348     }
    349 
    350   close (fd);
    351 
    352   // Read the ELF from disk now.  And add new data after data reading.
    353   fd = open (fname, O_RDONLY);
    354   if (fd == -1)
    355     {
    356       printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
    357       exit (1);
    358     }
    359 
    360   elf = read_elf (fd, use_mmap);
    361   check_section_size (elf, DATA_LEN);
    362   // Get (converted) data before adding new data.
    363   check_section_data (elf, DATA, DATA_LEN, 1);
    364 
    365   printf ("elf_getdata\n");
    366 
    367   // Now add more data.
    368   add_section_data (elf, DATA, DATA_LEN);
    369   check_section_size (elf, 2 * DATA_LEN);
    370   check_section_data (elf, DATA, DATA_LEN, 2);
    371 
    372   // And some more.
    373   add_section_data (elf, DATA, DATA_LEN);
    374   check_section_size (elf, 3 * DATA_LEN);
    375   check_section_data (elf, DATA, DATA_LEN, 3);
    376 
    377   if (elf_end (elf) != 0)
    378     {
    379       printf ("failure in elf_end: %s\n", elf_errmsg (-1));
    380       exit (1);
    381     }
    382 
    383   close (fd);
    384 
    385   unlink (fname);
    386 }
    387 
    388 int
    389 main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
    390 {
    391   // Initialize libelf.
    392   elf_version (EV_CURRENT);
    393 
    394   // Fill holes with something non-zero to more easily spot bad data.
    395   elf_fill ('X');
    396 
    397   check_elf (ELFCLASS32, 0);
    398   check_elf (ELFCLASS32, 1);
    399   check_elf (ELFCLASS64, 0);
    400   check_elf (ELFCLASS64, 1);
    401 
    402   return 0;
    403 }
    404