Home | History | Annotate | Download | only in tests
      1 /* Copyright (C) 2002, 2005 Red Hat, Inc.
      2    This file is part of Red Hat elfutils.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      4 
      5    Red Hat elfutils is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by the
      7    Free Software Foundation; version 2 of the License.
      8 
      9    Red Hat elfutils is distributed in the hope that it will be useful, but
     10    WITHOUT ANY WARRANTY; without even the implied warranty of
     11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12    General Public License for more details.
     13 
     14    You should have received a copy of the GNU General Public License along
     15    with Red Hat elfutils; if not, write to the Free Software Foundation,
     16    Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
     17 
     18    Red Hat elfutils is an included package of the Open Invention Network.
     19    An included package of the Open Invention Network is a package for which
     20    Open Invention Network licensees cross-license their patents.  No patent
     21    license is granted, either expressly or impliedly, by designation as an
     22    included package.  Should you wish to participate in the Open Invention
     23    Network licensing program, please visit www.openinventionnetwork.com
     24    <http://www.openinventionnetwork.com>.  */
     25 
     26 #ifdef HAVE_CONFIG_H
     27 # include <config.h>
     28 #endif
     29 
     30 #include <fcntl.h>
     31 #include ELFUTILS_HEADER(asm)
     32 #include <libelf.h>
     33 #include <stdio.h>
     34 #include <string.h>
     35 #include <unistd.h>
     36 
     37 
     38 static const char fname[] = "asm-tst2-out.o";
     39 
     40 
     41 static const GElf_Ehdr expected_ehdr =
     42   {
     43     .e_ident = { [EI_MAG0] = ELFMAG0,
     44 		 [EI_MAG1] = ELFMAG1,
     45 		 [EI_MAG2] = ELFMAG2,
     46 		 [EI_MAG3] = ELFMAG3,
     47 		 [EI_CLASS] = ELFCLASS32,
     48 		 [EI_DATA] = ELFDATA2LSB,
     49 		 [EI_VERSION] = EV_CURRENT },
     50     .e_type = ET_REL,
     51     .e_machine = EM_386,
     52     .e_version = EV_CURRENT,
     53     .e_shoff = 96,
     54     .e_ehsize = sizeof (Elf32_Ehdr),
     55     .e_shentsize = sizeof (Elf32_Shdr),
     56     .e_shnum = 3,
     57     .e_shstrndx = 2
     58   };
     59 
     60 
     61 static const char *scnnames[3] =
     62   {
     63     [0] = "",
     64     [1] = ".data",
     65     [2] = ".shstrtab"
     66   };
     67 
     68 
     69 int
     70 main (void)
     71 {
     72   AsmCtx_t *ctx;
     73   AsmScn_t *scn1;
     74   AsmScn_t *scn2;
     75   int result = 0;
     76   int fd;
     77   Elf *elf;
     78   GElf_Ehdr ehdr_mem;
     79   GElf_Ehdr *ehdr;
     80   size_t cnt;
     81 
     82   elf_version (EV_CURRENT);
     83 
     84   Ebl *ebl = ebl_openbackend_machine (EM_386);
     85   if (ebl == NULL)
     86     {
     87       puts ("cannot open backend library");
     88       return 1;
     89     }
     90 
     91   ctx = asm_begin (fname, ebl, false);
     92   if (ctx == NULL)
     93     {
     94       printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
     95       return 1;
     96     }
     97 
     98   /* Create two sections.  */
     99   scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
    100   scn2 = asm_newsubscn (scn1, 1);
    101   if (scn1 == NULL || scn2 == NULL)
    102     {
    103       printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
    104       asm_abort (ctx);
    105       return 1;
    106     }
    107 
    108   /* Special alignment for the .text section.  */
    109   if (asm_align (scn1, 16) != 0)
    110     {
    111       printf ("cannot align .text section: %s\n", asm_errmsg (-1));
    112       result = 1;
    113     }
    114 
    115   /* Add a few strings.  */
    116   if (asm_addstrz (scn1, "one", 4) != 0)
    117     {
    118       printf ("cannot insert first string: %s\n", asm_errmsg (-1));
    119       result = 1;
    120     }
    121   if (asm_addstrz (scn2, "three", 0) != 0)
    122     {
    123       printf ("cannot insert second string: %s\n", asm_errmsg (-1));
    124       result = 1;
    125     }
    126   if (asm_addstrz (scn1, "two", 4) != 0)
    127     {
    128       printf ("cannot insert third string: %s\n", asm_errmsg (-1));
    129       result = 1;
    130     }
    131 
    132   /* Create the output file.  */
    133   if (asm_end (ctx) != 0)
    134     {
    135       printf ("cannot create output file: %s\n", asm_errmsg (-1));
    136       asm_abort (ctx);
    137       return 1;
    138     }
    139 
    140   /* Check the file.  */
    141   fd = open (fname, O_RDONLY);
    142   if (fd == -1)
    143     {
    144       printf ("cannot open generated file: %m\n");
    145       result = 1;
    146       goto out;
    147     }
    148 
    149   elf = elf_begin (fd, ELF_C_READ, NULL);
    150   if (elf == NULL)
    151     {
    152       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
    153       result = 1;
    154       goto out_close;
    155     }
    156   if (elf_kind (elf) != ELF_K_ELF)
    157     {
    158       puts ("not a valid ELF file");
    159       result = 1;
    160       goto out_close2;
    161     }
    162 
    163   ehdr = gelf_getehdr (elf, &ehdr_mem);
    164   if (ehdr == NULL)
    165     {
    166       printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
    167       result = 1;
    168       goto out_close2;
    169     }
    170 
    171   if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
    172     {
    173       puts ("ELF header does not match");
    174       result = 1;
    175       goto out_close2;
    176     }
    177 
    178   for (cnt = 1; cnt < 3; ++cnt)
    179     {
    180       Elf_Scn *scn;
    181       GElf_Shdr shdr_mem;
    182       GElf_Shdr *shdr;
    183 
    184       scn = elf_getscn (elf, cnt);
    185       if (scn == NULL)
    186 	{
    187 	  printf ("cannot get section %Zd: %s\n", cnt, elf_errmsg (-1));
    188 	  result = 1;
    189 	  continue;
    190 	}
    191 
    192       shdr = gelf_getshdr (scn, &shdr_mem);
    193       if (shdr == NULL)
    194 	{
    195 	  printf ("cannot get section header for section %Zd: %s\n",
    196 		  cnt, elf_errmsg (-1));
    197 	  result = 1;
    198 	  continue;
    199 	}
    200 
    201       if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
    202 		  scnnames[cnt]) != 0)
    203 	{
    204 	  printf ("section %Zd's name differs: %s vs %s\n", cnt,
    205 		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
    206 		  scnnames[cnt]);
    207 	  result = 1;
    208 	}
    209 
    210       if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS))
    211 	{
    212 	  printf ("section %Zd's type differs\n", cnt);
    213 	  result = 1;
    214 	}
    215 
    216       if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
    217 	  || (cnt == 2 && shdr->sh_flags != 0))
    218 	{
    219 	  printf ("section %Zd's flags differs\n", cnt);
    220 	  result = 1;
    221 	}
    222 
    223       if (shdr->sh_addr != 0)
    224 	{
    225 	  printf ("section %Zd's address differs\n", cnt);
    226 	  result = 1;
    227 	}
    228 
    229       if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15))
    230 	  || (cnt == 2
    231 	      && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15)
    232 				     + strlen ("one") + 1
    233 				     + strlen ("two") + 1
    234 				     + strlen ("three") + 1)))
    235 	{
    236 	  printf ("section %Zd's offset differs\n", cnt);
    237 	  result = 1;
    238 	}
    239 
    240       if ((cnt == 1 && shdr->sh_size != (strlen ("one") + 1
    241 					 + strlen ("two") + 1
    242 					 + strlen ("three") + 1))
    243 	  || (cnt == 2 && shdr->sh_size != 17))
    244 	{
    245 	  printf ("section %Zd's size differs\n", cnt);
    246 	  result = 1;
    247 	}
    248 
    249       if (shdr->sh_link != 0)
    250 	{
    251 	  printf ("section %Zd's link differs\n", cnt);
    252 	  result = 1;
    253 	}
    254 
    255       if (shdr->sh_info != 0)
    256 	{
    257 	  printf ("section %Zd's info differs\n", cnt);
    258 	  result = 1;
    259 	}
    260 
    261       if ((cnt == 1 && shdr->sh_addralign != 16)
    262 	  || (cnt != 1 && shdr->sh_addralign != 1))
    263 	{
    264 	  printf ("section %Zd's addralign differs\n", cnt);
    265 	  result = 1;
    266 	}
    267 
    268       if (shdr->sh_entsize != 0)
    269 	{
    270 	  printf ("section %Zd's entsize differs\n", cnt);
    271 	  result = 1;
    272 	}
    273     }
    274 
    275  out_close2:
    276   elf_end (elf);
    277  out_close:
    278   close (fd);
    279  out:
    280   /* We don't need the file anymore.  */
    281   unlink (fname);
    282 
    283   ebl_closebackend (ebl);
    284 
    285   return result;
    286 }
    287