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