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