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