Home | History | Annotate | Download | only in tests
      1 /* Copyright (C) 2002, 2005 Red Hat, Inc.
      2    This file is part of elfutils.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      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 <fcntl.h>
     23 #include ELFUTILS_HEADER(asm)
     24 #include <libelf.h>
     25 #include <stdio.h>
     26 #include <string.h>
     27 #include <unistd.h>
     28 
     29 
     30 static const char fname[] = "asm-tst3-out.o";
     31 
     32 
     33 static const char *scnnames[5] =
     34   {
     35     [0] = "",
     36     [1] = ".data",
     37     [2] = ".strtab",
     38     [3] = ".symtab",
     39     [4] = ".shstrtab"
     40   };
     41 
     42 
     43 static unsigned int scntypes[5] =
     44   {
     45     [0] = SHT_NULL,
     46     [1] = SHT_PROGBITS,
     47     [2] = SHT_STRTAB,
     48     [3] = SHT_SYMTAB,
     49     [4] = SHT_STRTAB
     50   };
     51 
     52 
     53 int
     54 main (void)
     55 {
     56   AsmCtx_t *ctx;
     57   AsmScn_t *scn1;
     58   AsmScn_t *scn2;
     59   int result = 0;
     60   int fd;
     61   Elf *elf;
     62   GElf_Ehdr ehdr_mem;
     63   GElf_Ehdr *ehdr;
     64   size_t cnt;
     65 
     66   elf_version (EV_CURRENT);
     67 
     68   Ebl *ebl = ebl_openbackend_machine (EM_386);
     69   if (ebl == NULL)
     70     {
     71       puts ("cannot open backend library");
     72       return 1;
     73     }
     74 
     75   ctx = asm_begin (fname, ebl, false);
     76   if (ctx == NULL)
     77     {
     78       printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
     79       return 1;
     80     }
     81 
     82   /* Create two sections.  */
     83   scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
     84   scn2 = asm_newsubscn (scn1, 1);
     85   if (scn1 == NULL || scn2 == NULL)
     86     {
     87       printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
     88       asm_abort (ctx);
     89       return 1;
     90     }
     91 
     92   /* Special alignment for the .text section.  */
     93   if (asm_align (scn1, 16) != 0)
     94     {
     95       printf ("cannot align .text section: %s\n", asm_errmsg (-1));
     96       result = 1;
     97     }
     98 
     99   /* Add a few strings with names.  */
    100   if (asm_newsym (scn1, "one", 4, STT_OBJECT, STB_GLOBAL) == NULL)
    101     {
    102       printf ("cannot create first name: %s\n", asm_errmsg (-1));
    103       result = 1;
    104     }
    105   if (asm_addstrz (scn1, "one", 4) != 0)
    106     {
    107       printf ("cannot insert first string: %s\n", asm_errmsg (-1));
    108       result = 1;
    109     }
    110   if (asm_newsym (scn2, "three", 6, STT_OBJECT, STB_WEAK) == NULL)
    111     {
    112       printf ("cannot create second name: %s\n", asm_errmsg (-1));
    113       result = 1;
    114     }
    115   if (asm_addstrz (scn2, "three", 0) != 0)
    116     {
    117       printf ("cannot insert second string: %s\n", asm_errmsg (-1));
    118       result = 1;
    119     }
    120   if (asm_newsym (scn1, "two", 4, STT_OBJECT, STB_LOCAL) == NULL)
    121     {
    122       printf ("cannot create third name: %s\n", asm_errmsg (-1));
    123       result = 1;
    124     }
    125   if (asm_addstrz (scn1, "two", 4) != 0)
    126     {
    127       printf ("cannot insert third string: %s\n", asm_errmsg (-1));
    128       result = 1;
    129     }
    130 
    131   /* Create the output file.  */
    132   if (asm_end (ctx) != 0)
    133     {
    134       printf ("cannot create output file: %s\n", asm_errmsg (-1));
    135       asm_abort (ctx);
    136       return 1;
    137     }
    138 
    139   /* Check the file.  */
    140   fd = open (fname, O_RDONLY);
    141   if (fd == -1)
    142     {
    143       printf ("cannot open generated file: %m\n");
    144       result = 1;
    145       goto out;
    146     }
    147 
    148   elf = elf_begin (fd, ELF_C_READ, NULL);
    149   if (elf == NULL)
    150     {
    151       printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
    152       result = 1;
    153       goto out_close;
    154     }
    155   if (elf_kind (elf) != ELF_K_ELF)
    156     {
    157       puts ("not a valid ELF file");
    158       result = 1;
    159       goto out_close2;
    160     }
    161 
    162   ehdr = gelf_getehdr (elf, &ehdr_mem);
    163   if (ehdr == NULL)
    164     {
    165       printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
    166       result = 1;
    167       goto out_close2;
    168     }
    169 
    170   for (cnt = 1; cnt < 5; ++cnt)
    171     {
    172       Elf_Scn *scn;
    173       GElf_Shdr shdr_mem;
    174       GElf_Shdr *shdr;
    175 
    176       scn = elf_getscn (elf, cnt);
    177       if (scn == NULL)
    178 	{
    179 	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
    180 	  result = 1;
    181 	  continue;
    182 	}
    183 
    184       shdr = gelf_getshdr (scn, &shdr_mem);
    185       if (shdr == NULL)
    186 	{
    187 	  printf ("cannot get section header for section %zd: %s\n",
    188 		  cnt, elf_errmsg (-1));
    189 	  result = 1;
    190 	  continue;
    191 	}
    192 
    193       if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
    194 		  scnnames[cnt]) != 0)
    195 	{
    196 	  printf ("section %zd's name differs: %s vs %s\n", cnt,
    197 		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
    198 		  scnnames[cnt]);
    199 	  result = 1;
    200 	}
    201 
    202       if (shdr->sh_type != scntypes[cnt])
    203 	{
    204 	  printf ("section %zd's type differs\n", cnt);
    205 	  result = 1;
    206 	}
    207 
    208       if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
    209 	  || (cnt != 1 && shdr->sh_flags != 0))
    210 	{
    211 	  printf ("section %zd's flags differs\n", cnt);
    212 	  result = 1;
    213 	}
    214 
    215       if (shdr->sh_addr != 0)
    216 	{
    217 	  printf ("section %zd's address differs\n", cnt);
    218 	  result = 1;
    219 	}
    220 
    221       if (cnt == 3)
    222 	{
    223 	  Elf_Data *data;
    224 
    225 	  if (shdr->sh_link != 2)
    226 	    {
    227 	      puts ("symbol table has incorrect link");
    228 	      result = 1;
    229 	    }
    230 
    231 	  data = elf_getdata (scn, NULL);
    232 	  if (data == NULL)
    233 	    {
    234 	      puts ("cannot get data of symbol table");
    235 	      result = 1;
    236 	    }
    237 	  else
    238 	    {
    239 	      size_t inner;
    240 
    241 	      for (inner = 1;
    242 		   inner < (shdr->sh_size
    243 			    / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
    244 		   ++inner)
    245 		{
    246 		  GElf_Sym sym_mem;
    247 		  GElf_Sym *sym;
    248 
    249 		  sym = gelf_getsym (data, inner, &sym_mem);
    250 		  if (sym == NULL)
    251 		    {
    252 		      printf ("cannot get symbol %zu: %s\n",
    253 			      inner, elf_errmsg (-1));
    254 		      result = 1;
    255 		    }
    256 		  else
    257 		    {
    258 		      /* The order of the third and fourth entry depends
    259 			 on how the hash table is organized.  */
    260 		      static const char *names[4] =
    261 			{
    262 			  [0] = "",
    263 			  [1] = "two",
    264 			  [2] = "one",
    265 			  [3] = "three"
    266 			};
    267 		      static const int info[4] =
    268 			{
    269 			  [0] = GELF_ST_INFO (STB_LOCAL, STT_NOTYPE),
    270 			  [1] = GELF_ST_INFO (STB_LOCAL, STT_OBJECT),
    271 			  [2] = GELF_ST_INFO (STB_GLOBAL, STT_OBJECT),
    272 			  [3] = GELF_ST_INFO (STB_WEAK, STT_OBJECT)
    273 			};
    274 		      static const unsigned value[4] =
    275 			{
    276 			  [0] = 0,
    277 			  [1] = 4,
    278 			  [2] = 0,
    279 			  [3] = 8
    280 			};
    281 
    282 		      if (strcmp (names[inner],
    283 				  elf_strptr (elf, shdr->sh_link,
    284 					      sym->st_name)) != 0)
    285 			{
    286 			  printf ("symbol %zu has different name\n", inner);
    287 			  result = 1;
    288 			}
    289 
    290 		      if (sym->st_value != value[inner])
    291 			{
    292 			  printf ("symbol %zu has wrong value\n", inner);
    293 			  result = 1;
    294 			}
    295 
    296 		      if (sym->st_other != 0)
    297 			{
    298 			  printf ("symbol %zu has wrong other info\n", inner);
    299 			  result = 1;
    300 			}
    301 
    302 		      if (sym->st_shndx != 1)
    303 			{
    304 			  printf ("symbol %zu has wrong section reference\n",
    305 				  inner);
    306 			  result = 1;
    307 			}
    308 
    309 		      if (sym->st_info != info[inner])
    310 			{
    311 			  printf ("symbol %zu has wrong type or binding\n",
    312 				  inner);
    313 			  result = 1;
    314 			}
    315 
    316 		      if ((inner != 3 && sym->st_size != 4)
    317 			  || (inner == 3 && sym->st_size != 6))
    318 			{
    319 			  printf ("symbol %zu has wrong size\n", inner);
    320 			  result = 1;
    321 			}
    322 		    }
    323 		}
    324 	    }
    325 	}
    326     }
    327 
    328  out_close2:
    329   elf_end (elf);
    330  out_close:
    331   close (fd);
    332  out:
    333   /* We don't need the file anymore.  */
    334   unlink (fname);
    335 
    336   ebl_closebackend (ebl);
    337 
    338   return result;
    339 }
    340