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