1/* Copyright (C) 2002-2010 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 <inttypes.h> 24#include ELFUTILS_HEADER(asm) 25#include <libelf.h> 26#include <stdio.h> 27#include <string.h> 28#include <unistd.h> 29 30 31static const char fname[] = "asm-tst9-out.o"; 32 33 34static int32_t input[] = 35 { 36 0, 1, 129, 510, 2000, 33000, 0x7ffffff, 0x7fffffff 37 }; 38#define ninput (sizeof (input) / sizeof (input[0])) 39 40 41static const GElf_Ehdr expected_ehdr = 42 { 43 .e_ident = { [EI_MAG0] = ELFMAG0, 44 [EI_MAG1] = ELFMAG1, 45 [EI_MAG2] = ELFMAG2, 46 [EI_MAG3] = ELFMAG3, 47 [EI_CLASS] = ELFCLASS32, 48 [EI_DATA] = ELFDATA2LSB, 49 [EI_VERSION] = EV_CURRENT }, 50 .e_type = ET_REL, 51 .e_machine = EM_386, 52 .e_version = EV_CURRENT, 53 .e_shoff = 180, 54 .e_ehsize = sizeof (Elf32_Ehdr), 55 .e_shentsize = sizeof (Elf32_Shdr), 56 .e_shnum = 3, 57 .e_shstrndx = 2 58 }; 59 60 61static const char *scnnames[3] = 62 { 63 [0] = "", 64 [1] = ".data", 65 [2] = ".shstrtab" 66 }; 67 68 69static const char expecteddata[] = 70 { 71 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7f, 72 0x81, 0x01, 0x81, 0x01, 0xff, 0xfe, 0xff, 0xff, 0x0f, 0xff, 0x7e, 0xfe, 73 0x03, 0xfe, 0x03, 0x82, 0xfc, 0xff, 0xff, 0x0f, 0x82, 0x7c, 0xd0, 0x0f, 74 0xd0, 0x0f, 0xb0, 0xf0, 0xff, 0xff, 0x0f, 0xb0, 0x70, 0xe8, 0x81, 0x02, 75 0xe8, 0x81, 0x02, 0x98, 0xfe, 0xfd, 0xff, 0x0f, 0x98, 0xfe, 0x7d, 0xff, 76 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0x81, 0x80, 0x80, 0xc0, 0x0f, 77 0x81, 0x80, 0x80, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 78 0xff, 0x07, 0x81, 0x80, 0x80, 0x80, 0x08, 0x81, 0x80, 0x80, 0x80, 0x78 79 }; 80 81 82int 83main (void) 84{ 85 AsmCtx_t *ctx; 86 AsmScn_t *scn; 87 int result = 0; 88 int fd; 89 Elf *elf; 90 GElf_Ehdr ehdr_mem; 91 GElf_Ehdr *ehdr; 92 size_t cnt; 93 94 elf_version (EV_CURRENT); 95 96 Ebl *ebl = ebl_openbackend_machine (EM_386); 97 if (ebl == NULL) 98 { 99 puts ("cannot open backend library"); 100 return 1; 101 } 102 103 ctx = asm_begin (fname, ebl, false); 104 if (ctx == NULL) 105 { 106 printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); 107 return 1; 108 } 109 110 /* Create two sections. */ 111 scn = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); 112 if (scn == NULL) 113 { 114 printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); 115 asm_abort (ctx); 116 return 1; 117 } 118 119 /* Special alignment for the .text section. */ 120 if (asm_align (scn, 16) != 0) 121 { 122 printf ("cannot align .text section: %s\n", asm_errmsg (-1)); 123 result = 1; 124 } 125 126 /* Add a few ULEB128 and SLEB128 numbers. */ 127 for (cnt = 0; cnt < ninput; ++cnt) 128 { 129 if (asm_adduleb128 (scn, input[cnt]) != 0) 130 { 131 printf ("cannot insert uleb %" PRIu32 ": %s\n", 132 (uint32_t) input[cnt], asm_errmsg (-1)); 133 result = 1; 134 } 135 136 if (asm_addsleb128 (scn, input[cnt]) != 0) 137 { 138 printf ("cannot insert sleb %" PRId32 ": %s\n", 139 input[cnt], asm_errmsg (-1)); 140 result = 1; 141 } 142 143 if (asm_adduleb128 (scn, -input[cnt]) != 0) 144 { 145 printf ("cannot insert uleb %" PRIu32 ": %s\n", 146 (uint32_t) -input[cnt], asm_errmsg (-1)); 147 result = 1; 148 } 149 150 if (asm_addsleb128 (scn, -input[cnt]) != 0) 151 { 152 printf ("cannot insert sleb %" PRId32 ": %s\n", 153 -input[cnt], asm_errmsg (-1)); 154 result = 1; 155 } 156 } 157 158 /* Create the output file. */ 159 if (asm_end (ctx) != 0) 160 { 161 printf ("cannot create output file: %s\n", asm_errmsg (-1)); 162 asm_abort (ctx); 163 return 1; 164 } 165 166 /* Check the file. */ 167 fd = open (fname, O_RDONLY); 168 if (fd == -1) 169 { 170 printf ("cannot open generated file: %m\n"); 171 result = 1; 172 goto out; 173 } 174 175 elf = elf_begin (fd, ELF_C_READ, NULL); 176 if (elf == NULL) 177 { 178 printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); 179 result = 1; 180 goto out_close; 181 } 182 if (elf_kind (elf) != ELF_K_ELF) 183 { 184 puts ("not a valid ELF file"); 185 result = 1; 186 goto out_close2; 187 } 188 189 ehdr = gelf_getehdr (elf, &ehdr_mem); 190 if (ehdr == NULL) 191 { 192 printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); 193 result = 1; 194 goto out_close2; 195 } 196 197 if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0) 198 { 199 puts ("ELF header does not match"); 200 result = 1; 201 goto out_close2; 202 } 203 204 for (cnt = 1; cnt < 3; ++cnt) 205 { 206 Elf_Scn *escn; 207 GElf_Shdr shdr_mem; 208 GElf_Shdr *shdr; 209 210 escn = elf_getscn (elf, cnt); 211 if (escn == NULL) 212 { 213 printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); 214 result = 1; 215 continue; 216 } 217 218 shdr = gelf_getshdr (escn, &shdr_mem); 219 if (shdr == NULL) 220 { 221 printf ("cannot get section header for section %zd: %s\n", 222 cnt, elf_errmsg (-1)); 223 result = 1; 224 continue; 225 } 226 227 if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), 228 scnnames[cnt]) != 0) 229 { 230 printf ("section %zd's name differs: %s vs %s\n", cnt, 231 elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), 232 scnnames[cnt]); 233 result = 1; 234 } 235 236 if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS)) 237 { 238 printf ("section %zd's type differs\n", cnt); 239 result = 1; 240 } 241 242 if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) 243 || (cnt == 2 && shdr->sh_flags != 0)) 244 { 245 printf ("section %zd's flags differs\n", cnt); 246 result = 1; 247 } 248 249 if (shdr->sh_addr != 0) 250 { 251 printf ("section %zd's address differs\n", cnt); 252 result = 1; 253 } 254 255 if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15)) 256 || (cnt == 2 257 && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15) 258 + sizeof (expecteddata)))) 259 { 260 printf ("section %zd's offset differs\n", cnt); 261 result = 1; 262 } 263 264 if ((cnt == 1 && shdr->sh_size != sizeof (expecteddata)) 265 || (cnt == 2 && shdr->sh_size != 17)) 266 { 267 printf ("section %zd's size differs\n", cnt); 268 result = 1; 269 } 270 271 if (shdr->sh_link != 0) 272 { 273 printf ("section %zd's link differs\n", cnt); 274 result = 1; 275 } 276 277 if (shdr->sh_info != 0) 278 { 279 printf ("section %zd's info differs\n", cnt); 280 result = 1; 281 } 282 283 if ((cnt == 1 && shdr->sh_addralign != 16) 284 || (cnt != 1 && shdr->sh_addralign != 1)) 285 { 286 printf ("section %zd's addralign differs\n", cnt); 287 result = 1; 288 } 289 290 if (shdr->sh_entsize != 0) 291 { 292 printf ("section %zd's entsize differs\n", cnt); 293 result = 1; 294 } 295 296 if (cnt == 1) 297 { 298 Elf_Data *data = elf_getdata (escn, NULL); 299 300 if (data == NULL) 301 { 302 printf ("cannot get data of section %zd\n", cnt); 303 result = 1; 304 } 305 else 306 { 307 if (data->d_size != sizeof (expecteddata)) 308 { 309 printf ("data block size of section %zd wrong: got %zd, " 310 "expected 96\n", cnt, data->d_size); 311 result = 1; 312 } 313 314 if (memcmp (data->d_buf, expecteddata, sizeof (expecteddata)) 315 != 0) 316 { 317 printf ("data block content of section %zd wrong\n", cnt); 318 result = 1; 319 } 320 } 321 } 322 } 323 324 out_close2: 325 elf_end (elf); 326 out_close: 327 close (fd); 328 out: 329 /* We don't need the file anymore. */ 330 unlink (fname); 331 332 ebl_closebackend (ebl); 333 334 return result; 335} 336