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 ELFUTILS_HEADER(ebl) 25#include <libelf.h> 26#include <stdio.h> 27#include <string.h> 28#include <unistd.h> 29 30 31static const char fname[] = "asm-tst3-out.o"; 32 33 34static const char *scnnames[5] = 35 { 36 [0] = "", 37 [1] = ".data", 38 [2] = ".strtab", 39 [3] = ".symtab", 40 [4] = ".shstrtab" 41 }; 42 43 44static 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 54int 55main (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