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-tst2-out.o"; 32 33 34static const GElf_Ehdr expected_ehdr = 35 { 36 .e_ident = { [EI_MAG0] = ELFMAG0, 37 [EI_MAG1] = ELFMAG1, 38 [EI_MAG2] = ELFMAG2, 39 [EI_MAG3] = ELFMAG3, 40 [EI_CLASS] = ELFCLASS32, 41 [EI_DATA] = ELFDATA2LSB, 42 [EI_VERSION] = EV_CURRENT }, 43 .e_type = ET_REL, 44 .e_machine = EM_386, 45 .e_version = EV_CURRENT, 46 .e_shoff = 96, 47 .e_ehsize = sizeof (Elf32_Ehdr), 48 .e_shentsize = sizeof (Elf32_Shdr), 49 .e_shnum = 3, 50 .e_shstrndx = 2 51 }; 52 53 54static const char *scnnames[3] = 55 { 56 [0] = "", 57 [1] = ".data", 58 [2] = ".shstrtab" 59 }; 60 61 62int 63main (void) 64{ 65 AsmCtx_t *ctx; 66 AsmScn_t *scn1; 67 AsmScn_t *scn2; 68 int result = 0; 69 int fd; 70 Elf *elf; 71 GElf_Ehdr ehdr_mem; 72 GElf_Ehdr *ehdr; 73 size_t cnt; 74 75 elf_version (EV_CURRENT); 76 77 Ebl *ebl = ebl_openbackend_machine (EM_386); 78 if (ebl == NULL) 79 { 80 puts ("cannot open backend library"); 81 return 1; 82 } 83 84 ctx = asm_begin (fname, ebl, false); 85 if (ctx == NULL) 86 { 87 printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); 88 return 1; 89 } 90 91 /* Create two sections. */ 92 scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 93 scn2 = asm_newsubscn (scn1, 1); 94 if (scn1 == NULL || scn2 == NULL) 95 { 96 printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); 97 asm_abort (ctx); 98 return 1; 99 } 100 101 /* Special alignment for the .text section. */ 102 if (asm_align (scn1, 16) != 0) 103 { 104 printf ("cannot align .text section: %s\n", asm_errmsg (-1)); 105 result = 1; 106 } 107 108 /* Add a few strings. */ 109 if (asm_addstrz (scn1, "one", 4) != 0) 110 { 111 printf ("cannot insert first string: %s\n", asm_errmsg (-1)); 112 result = 1; 113 } 114 if (asm_addstrz (scn2, "three", 0) != 0) 115 { 116 printf ("cannot insert second string: %s\n", asm_errmsg (-1)); 117 result = 1; 118 } 119 if (asm_addstrz (scn1, "two", 4) != 0) 120 { 121 printf ("cannot insert third string: %s\n", asm_errmsg (-1)); 122 result = 1; 123 } 124 125 /* Create the output file. */ 126 if (asm_end (ctx) != 0) 127 { 128 printf ("cannot create output file: %s\n", asm_errmsg (-1)); 129 asm_abort (ctx); 130 return 1; 131 } 132 133 /* Check the file. */ 134 fd = open (fname, O_RDONLY); 135 if (fd == -1) 136 { 137 printf ("cannot open generated file: %m\n"); 138 result = 1; 139 goto out; 140 } 141 142 elf = elf_begin (fd, ELF_C_READ, NULL); 143 if (elf == NULL) 144 { 145 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 146 result = 1; 147 goto out_close; 148 } 149 if (elf_kind (elf) != ELF_K_ELF) 150 { 151 puts ("not a valid ELF file"); 152 result = 1; 153 goto out_close2; 154 } 155 156 ehdr = gelf_getehdr (elf, &ehdr_mem); 157 if (ehdr == NULL) 158 { 159 printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 160 result = 1; 161 goto out_close2; 162 } 163 164 if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0) 165 { 166 puts ("ELF header does not match"); 167 result = 1; 168 goto out_close2; 169 } 170 171 for (cnt = 1; cnt < 3; ++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 != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS)) 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 == 2 && 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 == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15)) 223 || (cnt == 2 224 && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15) 225 + strlen ("one") + 1 226 + strlen ("two") + 1 227 + strlen ("three") + 1))) 228 { 229 printf ("section %zd's offset differs\n", cnt); 230 result = 1; 231 } 232 233 if ((cnt == 1 && shdr->sh_size != (strlen ("one") + 1 234 + strlen ("two") + 1 235 + strlen ("three") + 1)) 236 || (cnt == 2 && shdr->sh_size != 17)) 237 { 238 printf ("section %zd's size differs\n", cnt); 239 result = 1; 240 } 241 242 if (shdr->sh_link != 0) 243 { 244 printf ("section %zd's link differs\n", cnt); 245 result = 1; 246 } 247 248 if (shdr->sh_info != 0) 249 { 250 printf ("section %zd's info differs\n", cnt); 251 result = 1; 252 } 253 254 if ((cnt == 1 && shdr->sh_addralign != 16) 255 || (cnt != 1 && shdr->sh_addralign != 1)) 256 { 257 printf ("section %zd's addralign differs\n", cnt); 258 result = 1; 259 } 260 261 if (shdr->sh_entsize != 0) 262 { 263 printf ("section %zd's entsize differs\n", cnt); 264 result = 1; 265 } 266 } 267 268 out_close2: 269 elf_end (elf); 270 out_close: 271 close (fd); 272 out: 273 /* We don't need the file anymore. */ 274 unlink (fname); 275 276 ebl_closebackend (ebl); 277 278 return result; 279} 280