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