• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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(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
main(void)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