1da0c48c4Sopenharmony_ci/* Copyright (C) 2002, 2005 Red Hat, Inc. 2da0c48c4Sopenharmony_ci This file is part of elfutils. 3da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2002. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of the GNU General Public License as published by 7da0c48c4Sopenharmony_ci the Free Software Foundation; either version 3 of the License, or 8da0c48c4Sopenharmony_ci (at your option) any later version. 9da0c48c4Sopenharmony_ci 10da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 11da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 12da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13da0c48c4Sopenharmony_ci GNU General Public License for more details. 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci You should have received a copy of the GNU General Public License 16da0c48c4Sopenharmony_ci along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 19da0c48c4Sopenharmony_ci# include <config.h> 20da0c48c4Sopenharmony_ci#endif 21da0c48c4Sopenharmony_ci 22da0c48c4Sopenharmony_ci#include <fcntl.h> 23da0c48c4Sopenharmony_ci#include ELFUTILS_HEADER(asm) 24da0c48c4Sopenharmony_ci#include ELFUTILS_HEADER(ebl) 25da0c48c4Sopenharmony_ci#include <libelf.h> 26da0c48c4Sopenharmony_ci#include <stdio.h> 27da0c48c4Sopenharmony_ci#include <string.h> 28da0c48c4Sopenharmony_ci#include <unistd.h> 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci 31da0c48c4Sopenharmony_cistatic const char fname[] = "asm-tst3-out.o"; 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_cistatic const char *scnnames[5] = 35da0c48c4Sopenharmony_ci { 36da0c48c4Sopenharmony_ci [0] = "", 37da0c48c4Sopenharmony_ci [1] = ".data", 38da0c48c4Sopenharmony_ci [2] = ".strtab", 39da0c48c4Sopenharmony_ci [3] = ".symtab", 40da0c48c4Sopenharmony_ci [4] = ".shstrtab" 41da0c48c4Sopenharmony_ci }; 42da0c48c4Sopenharmony_ci 43da0c48c4Sopenharmony_ci 44da0c48c4Sopenharmony_cistatic unsigned int scntypes[5] = 45da0c48c4Sopenharmony_ci { 46da0c48c4Sopenharmony_ci [0] = SHT_NULL, 47da0c48c4Sopenharmony_ci [1] = SHT_PROGBITS, 48da0c48c4Sopenharmony_ci [2] = SHT_STRTAB, 49da0c48c4Sopenharmony_ci [3] = SHT_SYMTAB, 50da0c48c4Sopenharmony_ci [4] = SHT_STRTAB 51da0c48c4Sopenharmony_ci }; 52da0c48c4Sopenharmony_ci 53da0c48c4Sopenharmony_ci 54da0c48c4Sopenharmony_ciint 55da0c48c4Sopenharmony_cimain (void) 56da0c48c4Sopenharmony_ci{ 57da0c48c4Sopenharmony_ci AsmCtx_t *ctx; 58da0c48c4Sopenharmony_ci AsmScn_t *scn1; 59da0c48c4Sopenharmony_ci AsmScn_t *scn2; 60da0c48c4Sopenharmony_ci int result = 0; 61da0c48c4Sopenharmony_ci int fd; 62da0c48c4Sopenharmony_ci Elf *elf; 63da0c48c4Sopenharmony_ci GElf_Ehdr ehdr_mem; 64da0c48c4Sopenharmony_ci GElf_Ehdr *ehdr; 65da0c48c4Sopenharmony_ci size_t cnt; 66da0c48c4Sopenharmony_ci 67da0c48c4Sopenharmony_ci elf_version (EV_CURRENT); 68da0c48c4Sopenharmony_ci 69da0c48c4Sopenharmony_ci Ebl *ebl = ebl_openbackend_machine (EM_386); 70da0c48c4Sopenharmony_ci if (ebl == NULL) 71da0c48c4Sopenharmony_ci { 72da0c48c4Sopenharmony_ci puts ("cannot open backend library"); 73da0c48c4Sopenharmony_ci return 1; 74da0c48c4Sopenharmony_ci } 75da0c48c4Sopenharmony_ci 76da0c48c4Sopenharmony_ci ctx = asm_begin (fname, ebl, false); 77da0c48c4Sopenharmony_ci if (ctx == NULL) 78da0c48c4Sopenharmony_ci { 79da0c48c4Sopenharmony_ci printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); 80da0c48c4Sopenharmony_ci return 1; 81da0c48c4Sopenharmony_ci } 82da0c48c4Sopenharmony_ci 83da0c48c4Sopenharmony_ci /* Create two sections. */ 84da0c48c4Sopenharmony_ci scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 85da0c48c4Sopenharmony_ci scn2 = asm_newsubscn (scn1, 1); 86da0c48c4Sopenharmony_ci if (scn1 == NULL || scn2 == NULL) 87da0c48c4Sopenharmony_ci { 88da0c48c4Sopenharmony_ci printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); 89da0c48c4Sopenharmony_ci asm_abort (ctx); 90da0c48c4Sopenharmony_ci return 1; 91da0c48c4Sopenharmony_ci } 92da0c48c4Sopenharmony_ci 93da0c48c4Sopenharmony_ci /* Special alignment for the .text section. */ 94da0c48c4Sopenharmony_ci if (asm_align (scn1, 16) != 0) 95da0c48c4Sopenharmony_ci { 96da0c48c4Sopenharmony_ci printf ("cannot align .text section: %s\n", asm_errmsg (-1)); 97da0c48c4Sopenharmony_ci result = 1; 98da0c48c4Sopenharmony_ci } 99da0c48c4Sopenharmony_ci 100da0c48c4Sopenharmony_ci /* Add a few strings with names. */ 101da0c48c4Sopenharmony_ci if (asm_newsym (scn1, "one", 4, STT_OBJECT, STB_GLOBAL) == NULL) 102da0c48c4Sopenharmony_ci { 103da0c48c4Sopenharmony_ci printf ("cannot create first name: %s\n", asm_errmsg (-1)); 104da0c48c4Sopenharmony_ci result = 1; 105da0c48c4Sopenharmony_ci } 106da0c48c4Sopenharmony_ci if (asm_addstrz (scn1, "one", 4) != 0) 107da0c48c4Sopenharmony_ci { 108da0c48c4Sopenharmony_ci printf ("cannot insert first string: %s\n", asm_errmsg (-1)); 109da0c48c4Sopenharmony_ci result = 1; 110da0c48c4Sopenharmony_ci } 111da0c48c4Sopenharmony_ci if (asm_newsym (scn2, "three", 6, STT_OBJECT, STB_WEAK) == NULL) 112da0c48c4Sopenharmony_ci { 113da0c48c4Sopenharmony_ci printf ("cannot create second name: %s\n", asm_errmsg (-1)); 114da0c48c4Sopenharmony_ci result = 1; 115da0c48c4Sopenharmony_ci } 116da0c48c4Sopenharmony_ci if (asm_addstrz (scn2, "three", 0) != 0) 117da0c48c4Sopenharmony_ci { 118da0c48c4Sopenharmony_ci printf ("cannot insert second string: %s\n", asm_errmsg (-1)); 119da0c48c4Sopenharmony_ci result = 1; 120da0c48c4Sopenharmony_ci } 121da0c48c4Sopenharmony_ci if (asm_newsym (scn1, "two", 4, STT_OBJECT, STB_LOCAL) == NULL) 122da0c48c4Sopenharmony_ci { 123da0c48c4Sopenharmony_ci printf ("cannot create third name: %s\n", asm_errmsg (-1)); 124da0c48c4Sopenharmony_ci result = 1; 125da0c48c4Sopenharmony_ci } 126da0c48c4Sopenharmony_ci if (asm_addstrz (scn1, "two", 4) != 0) 127da0c48c4Sopenharmony_ci { 128da0c48c4Sopenharmony_ci printf ("cannot insert third string: %s\n", asm_errmsg (-1)); 129da0c48c4Sopenharmony_ci result = 1; 130da0c48c4Sopenharmony_ci } 131da0c48c4Sopenharmony_ci 132da0c48c4Sopenharmony_ci /* Create the output file. */ 133da0c48c4Sopenharmony_ci if (asm_end (ctx) != 0) 134da0c48c4Sopenharmony_ci { 135da0c48c4Sopenharmony_ci printf ("cannot create output file: %s\n", asm_errmsg (-1)); 136da0c48c4Sopenharmony_ci asm_abort (ctx); 137da0c48c4Sopenharmony_ci return 1; 138da0c48c4Sopenharmony_ci } 139da0c48c4Sopenharmony_ci 140da0c48c4Sopenharmony_ci /* Check the file. */ 141da0c48c4Sopenharmony_ci fd = open (fname, O_RDONLY); 142da0c48c4Sopenharmony_ci if (fd == -1) 143da0c48c4Sopenharmony_ci { 144da0c48c4Sopenharmony_ci printf ("cannot open generated file: %m\n"); 145da0c48c4Sopenharmony_ci result = 1; 146da0c48c4Sopenharmony_ci goto out; 147da0c48c4Sopenharmony_ci } 148da0c48c4Sopenharmony_ci 149da0c48c4Sopenharmony_ci elf = elf_begin (fd, ELF_C_READ, NULL); 150da0c48c4Sopenharmony_ci if (elf == NULL) 151da0c48c4Sopenharmony_ci { 152da0c48c4Sopenharmony_ci printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 153da0c48c4Sopenharmony_ci result = 1; 154da0c48c4Sopenharmony_ci goto out_close; 155da0c48c4Sopenharmony_ci } 156da0c48c4Sopenharmony_ci if (elf_kind (elf) != ELF_K_ELF) 157da0c48c4Sopenharmony_ci { 158da0c48c4Sopenharmony_ci puts ("not a valid ELF file"); 159da0c48c4Sopenharmony_ci result = 1; 160da0c48c4Sopenharmony_ci goto out_close2; 161da0c48c4Sopenharmony_ci } 162da0c48c4Sopenharmony_ci 163da0c48c4Sopenharmony_ci ehdr = gelf_getehdr (elf, &ehdr_mem); 164da0c48c4Sopenharmony_ci if (ehdr == NULL) 165da0c48c4Sopenharmony_ci { 166da0c48c4Sopenharmony_ci printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 167da0c48c4Sopenharmony_ci result = 1; 168da0c48c4Sopenharmony_ci goto out_close2; 169da0c48c4Sopenharmony_ci } 170da0c48c4Sopenharmony_ci 171da0c48c4Sopenharmony_ci for (cnt = 1; cnt < 5; ++cnt) 172da0c48c4Sopenharmony_ci { 173da0c48c4Sopenharmony_ci Elf_Scn *scn; 174da0c48c4Sopenharmony_ci GElf_Shdr shdr_mem; 175da0c48c4Sopenharmony_ci GElf_Shdr *shdr; 176da0c48c4Sopenharmony_ci 177da0c48c4Sopenharmony_ci scn = elf_getscn (elf, cnt); 178da0c48c4Sopenharmony_ci if (scn == NULL) 179da0c48c4Sopenharmony_ci { 180da0c48c4Sopenharmony_ci printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); 181da0c48c4Sopenharmony_ci result = 1; 182da0c48c4Sopenharmony_ci continue; 183da0c48c4Sopenharmony_ci } 184da0c48c4Sopenharmony_ci 185da0c48c4Sopenharmony_ci shdr = gelf_getshdr (scn, &shdr_mem); 186da0c48c4Sopenharmony_ci if (shdr == NULL) 187da0c48c4Sopenharmony_ci { 188da0c48c4Sopenharmony_ci printf ("cannot get section header for section %zd: %s\n", 189da0c48c4Sopenharmony_ci cnt, elf_errmsg (-1)); 190da0c48c4Sopenharmony_ci result = 1; 191da0c48c4Sopenharmony_ci continue; 192da0c48c4Sopenharmony_ci } 193da0c48c4Sopenharmony_ci 194da0c48c4Sopenharmony_ci if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), 195da0c48c4Sopenharmony_ci scnnames[cnt]) != 0) 196da0c48c4Sopenharmony_ci { 197da0c48c4Sopenharmony_ci printf ("section %zd's name differs: %s vs %s\n", cnt, 198da0c48c4Sopenharmony_ci elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), 199da0c48c4Sopenharmony_ci scnnames[cnt]); 200da0c48c4Sopenharmony_ci result = 1; 201da0c48c4Sopenharmony_ci } 202da0c48c4Sopenharmony_ci 203da0c48c4Sopenharmony_ci if (shdr->sh_type != scntypes[cnt]) 204da0c48c4Sopenharmony_ci { 205da0c48c4Sopenharmony_ci printf ("section %zd's type differs\n", cnt); 206da0c48c4Sopenharmony_ci result = 1; 207da0c48c4Sopenharmony_ci } 208da0c48c4Sopenharmony_ci 209da0c48c4Sopenharmony_ci if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) 210da0c48c4Sopenharmony_ci || (cnt != 1 && shdr->sh_flags != 0)) 211da0c48c4Sopenharmony_ci { 212da0c48c4Sopenharmony_ci printf ("section %zd's flags differs\n", cnt); 213da0c48c4Sopenharmony_ci result = 1; 214da0c48c4Sopenharmony_ci } 215da0c48c4Sopenharmony_ci 216da0c48c4Sopenharmony_ci if (shdr->sh_addr != 0) 217da0c48c4Sopenharmony_ci { 218da0c48c4Sopenharmony_ci printf ("section %zd's address differs\n", cnt); 219da0c48c4Sopenharmony_ci result = 1; 220da0c48c4Sopenharmony_ci } 221da0c48c4Sopenharmony_ci 222da0c48c4Sopenharmony_ci if (cnt == 3) 223da0c48c4Sopenharmony_ci { 224da0c48c4Sopenharmony_ci Elf_Data *data; 225da0c48c4Sopenharmony_ci 226da0c48c4Sopenharmony_ci if (shdr->sh_link != 2) 227da0c48c4Sopenharmony_ci { 228da0c48c4Sopenharmony_ci puts ("symbol table has incorrect link"); 229da0c48c4Sopenharmony_ci result = 1; 230da0c48c4Sopenharmony_ci } 231da0c48c4Sopenharmony_ci 232da0c48c4Sopenharmony_ci data = elf_getdata (scn, NULL); 233da0c48c4Sopenharmony_ci if (data == NULL) 234da0c48c4Sopenharmony_ci { 235da0c48c4Sopenharmony_ci puts ("cannot get data of symbol table"); 236da0c48c4Sopenharmony_ci result = 1; 237da0c48c4Sopenharmony_ci } 238da0c48c4Sopenharmony_ci else 239da0c48c4Sopenharmony_ci { 240da0c48c4Sopenharmony_ci size_t inner; 241da0c48c4Sopenharmony_ci 242da0c48c4Sopenharmony_ci for (inner = 1; 243da0c48c4Sopenharmony_ci inner < (shdr->sh_size 244da0c48c4Sopenharmony_ci / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT)); 245da0c48c4Sopenharmony_ci ++inner) 246da0c48c4Sopenharmony_ci { 247da0c48c4Sopenharmony_ci GElf_Sym sym_mem; 248da0c48c4Sopenharmony_ci GElf_Sym *sym; 249da0c48c4Sopenharmony_ci 250da0c48c4Sopenharmony_ci sym = gelf_getsym (data, inner, &sym_mem); 251da0c48c4Sopenharmony_ci if (sym == NULL) 252da0c48c4Sopenharmony_ci { 253da0c48c4Sopenharmony_ci printf ("cannot get symbol %zu: %s\n", 254da0c48c4Sopenharmony_ci inner, elf_errmsg (-1)); 255da0c48c4Sopenharmony_ci result = 1; 256da0c48c4Sopenharmony_ci } 257da0c48c4Sopenharmony_ci else 258da0c48c4Sopenharmony_ci { 259da0c48c4Sopenharmony_ci /* The order of the third and fourth entry depends 260da0c48c4Sopenharmony_ci on how the hash table is organized. */ 261da0c48c4Sopenharmony_ci static const char *names[4] = 262da0c48c4Sopenharmony_ci { 263da0c48c4Sopenharmony_ci [0] = "", 264da0c48c4Sopenharmony_ci [1] = "two", 265da0c48c4Sopenharmony_ci [2] = "one", 266da0c48c4Sopenharmony_ci [3] = "three" 267da0c48c4Sopenharmony_ci }; 268da0c48c4Sopenharmony_ci static const int info[4] = 269da0c48c4Sopenharmony_ci { 270da0c48c4Sopenharmony_ci [0] = GELF_ST_INFO (STB_LOCAL, STT_NOTYPE), 271da0c48c4Sopenharmony_ci [1] = GELF_ST_INFO (STB_LOCAL, STT_OBJECT), 272da0c48c4Sopenharmony_ci [2] = GELF_ST_INFO (STB_GLOBAL, STT_OBJECT), 273da0c48c4Sopenharmony_ci [3] = GELF_ST_INFO (STB_WEAK, STT_OBJECT) 274da0c48c4Sopenharmony_ci }; 275da0c48c4Sopenharmony_ci static const unsigned value[4] = 276da0c48c4Sopenharmony_ci { 277da0c48c4Sopenharmony_ci [0] = 0, 278da0c48c4Sopenharmony_ci [1] = 4, 279da0c48c4Sopenharmony_ci [2] = 0, 280da0c48c4Sopenharmony_ci [3] = 8 281da0c48c4Sopenharmony_ci }; 282da0c48c4Sopenharmony_ci 283da0c48c4Sopenharmony_ci if (strcmp (names[inner], 284da0c48c4Sopenharmony_ci elf_strptr (elf, shdr->sh_link, 285da0c48c4Sopenharmony_ci sym->st_name)) != 0) 286da0c48c4Sopenharmony_ci { 287da0c48c4Sopenharmony_ci printf ("symbol %zu has different name\n", inner); 288da0c48c4Sopenharmony_ci result = 1; 289da0c48c4Sopenharmony_ci } 290da0c48c4Sopenharmony_ci 291da0c48c4Sopenharmony_ci if (sym->st_value != value[inner]) 292da0c48c4Sopenharmony_ci { 293da0c48c4Sopenharmony_ci printf ("symbol %zu has wrong value\n", inner); 294da0c48c4Sopenharmony_ci result = 1; 295da0c48c4Sopenharmony_ci } 296da0c48c4Sopenharmony_ci 297da0c48c4Sopenharmony_ci if (sym->st_other != 0) 298da0c48c4Sopenharmony_ci { 299da0c48c4Sopenharmony_ci printf ("symbol %zu has wrong other info\n", inner); 300da0c48c4Sopenharmony_ci result = 1; 301da0c48c4Sopenharmony_ci } 302da0c48c4Sopenharmony_ci 303da0c48c4Sopenharmony_ci if (sym->st_shndx != 1) 304da0c48c4Sopenharmony_ci { 305da0c48c4Sopenharmony_ci printf ("symbol %zu has wrong section reference\n", 306da0c48c4Sopenharmony_ci inner); 307da0c48c4Sopenharmony_ci result = 1; 308da0c48c4Sopenharmony_ci } 309da0c48c4Sopenharmony_ci 310da0c48c4Sopenharmony_ci if (sym->st_info != info[inner]) 311da0c48c4Sopenharmony_ci { 312da0c48c4Sopenharmony_ci printf ("symbol %zu has wrong type or binding\n", 313da0c48c4Sopenharmony_ci inner); 314da0c48c4Sopenharmony_ci result = 1; 315da0c48c4Sopenharmony_ci } 316da0c48c4Sopenharmony_ci 317da0c48c4Sopenharmony_ci if ((inner != 3 && sym->st_size != 4) 318da0c48c4Sopenharmony_ci || (inner == 3 && sym->st_size != 6)) 319da0c48c4Sopenharmony_ci { 320da0c48c4Sopenharmony_ci printf ("symbol %zu has wrong size\n", inner); 321da0c48c4Sopenharmony_ci result = 1; 322da0c48c4Sopenharmony_ci } 323da0c48c4Sopenharmony_ci } 324da0c48c4Sopenharmony_ci } 325da0c48c4Sopenharmony_ci } 326da0c48c4Sopenharmony_ci } 327da0c48c4Sopenharmony_ci } 328da0c48c4Sopenharmony_ci 329da0c48c4Sopenharmony_ci out_close2: 330da0c48c4Sopenharmony_ci elf_end (elf); 331da0c48c4Sopenharmony_ci out_close: 332da0c48c4Sopenharmony_ci close (fd); 333da0c48c4Sopenharmony_ci out: 334da0c48c4Sopenharmony_ci /* We don't need the file anymore. */ 335da0c48c4Sopenharmony_ci unlink (fname); 336da0c48c4Sopenharmony_ci 337da0c48c4Sopenharmony_ci ebl_closebackend (ebl); 338da0c48c4Sopenharmony_ci 339da0c48c4Sopenharmony_ci return result; 340da0c48c4Sopenharmony_ci} 341