From 5f0dbf648ef5f8f4e6328cd975e69d5c62d225c3 Mon Sep 17 00:00:00 2001 From: Packit Date: Oct 13 2020 09:46:55 +0000 Subject: Apply patch elfutils-0.178-libasm-ebl.patch patch_name: elfutils-0.178-libasm-ebl.patch present_in_specfile: true --- diff --git a/libasm/libasm.h b/libasm/libasm.h index 5c61224..a45c9fa 100644 --- a/libasm/libasm.h +++ b/libasm/libasm.h @@ -32,7 +32,7 @@ #include #include -#include +typedef struct ebl Ebl; /* Opaque type for the assembler context descriptor. */ diff --git a/libasm/libasm.h.libasm-ebl b/libasm/libasm.h.libasm-ebl new file mode 100644 index 0000000..5c61224 --- /dev/null +++ b/libasm/libasm.h.libasm-ebl @@ -0,0 +1,202 @@ +/* Interface for libasm. + Copyright (C) 2002, 2005, 2008 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBASM_H +#define _LIBASM_H 1 + +#include +#include + +#include + + +/* Opaque type for the assembler context descriptor. */ +typedef struct AsmCtx AsmCtx_t; + +/* Opaque type for a section. */ +typedef struct AsmScn AsmScn_t; + +/* Opaque type for a section group. */ +typedef struct AsmScnGrp AsmScnGrp_t; + +/* Opaque type for a symbol. */ +typedef struct AsmSym AsmSym_t; + + +/* Opaque type for the disassembler context descriptor. */ +typedef struct DisasmCtx DisasmCtx_t; + +/* Type used for callback functions to retrieve symbol name. The + symbol reference is in the section designated by the second parameter + at an offset described by the first parameter. The value is the + third parameter. */ +typedef int (*DisasmGetSymCB_t) (GElf_Addr, Elf32_Word, GElf_Addr, char **, + size_t *, void *); + +/* Output function callback. */ +typedef int (*DisasmOutputCB_t) (char *, size_t, void *); + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create output file and return descriptor for assembler context. If + TEXTP is true the output is an assembler format text file. + Otherwise an object file is created. The MACHINE parameter + corresponds to an EM_ constant from , KLASS specifies the + class (32- or 64-bit), and DATA specifies the byte order (little or + big endian). */ +extern AsmCtx_t *asm_begin (const char *fname, Ebl *ebl, bool textp); + +/* Abort the operation on the assembler context and free all resources. */ +extern int asm_abort (AsmCtx_t *ctx); + +/* Finalize output file and free all resources. */ +extern int asm_end (AsmCtx_t *ctx); + + +/* Return handle for the named section. If it was not used before + create it. */ +extern AsmScn_t *asm_newscn (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags); + + +/* Similar to 'asm_newscn', but make it part of section group GRP. */ +extern AsmScn_t *asm_newscn_ingrp (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags, + AsmScnGrp_t *grp); + +/* Create new subsection NR in the given section. */ +extern AsmScn_t *asm_newsubscn (AsmScn_t *asmscn, unsigned int nr); + + +/* Return handle for new section group. The signature symbol can be + set later. */ +extern AsmScnGrp_t *asm_newscngrp (AsmCtx_t *ctx, const char *grpname, + AsmSym_t *signature, Elf32_Word flags); + +/* Set or overwrite signature symbol for group. */ +extern int asm_scngrp_newsignature (AsmScnGrp_t *grp, AsmSym_t *signature); + + +/* Add zero terminated string STR of size LEN to (sub)section ASMSCN. */ +extern int asm_addstrz (AsmScn_t *asmscn, const char *str, size_t len); + +/* Add 8-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint8 (AsmScn_t *asmscn, int8_t num); + +/* Add 8-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint8 (AsmScn_t *asmscn, uint8_t num); + +/* Add 16-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint16 (AsmScn_t *asmscn, int16_t num); + +/* Add 16-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint16 (AsmScn_t *asmscn, uint16_t num); + +/* Add 32-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint32 (AsmScn_t *asmscn, int32_t num); + +/* Add 32-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint32 (AsmScn_t *asmscn, uint32_t num); + +/* Add 64-bit signed integer NUM to (sub)section ASMSCN. */ +extern int asm_addint64 (AsmScn_t *asmscn, int64_t num); + +/* Add 64-bit unsigned integer NUM to (sub)section ASMSCN. */ +extern int asm_adduint64 (AsmScn_t *asmscn, uint64_t num); + + +/* Add signed little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_addsleb128 (AsmScn_t *asmscn, int32_t num); + +/* Add unsigned little endian base 128 integer NUM to (sub)section ASMSCN. */ +extern int asm_adduleb128 (AsmScn_t *asmscn, uint32_t num); + + +/* Define new symbol NAME for current position in given section ASMSCN. */ +extern AsmSym_t *asm_newsym (AsmScn_t *asmscn, const char *name, + GElf_Xword size, int type, int binding); + + +/* Define new common symbol NAME with given SIZE and alignment. */ +extern AsmSym_t *asm_newcomsym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr align); + +/* Define new common symbol NAME with given SIZE, VALUE, TYPE, and BINDING. */ +extern AsmSym_t *asm_newabssym (AsmCtx_t *ctx, const char *name, + GElf_Xword size, GElf_Addr value, + int type, int binding); + + +/* Align (sub)section offset according to VALUE. */ +extern int asm_align (AsmScn_t *asmscn, GElf_Word value); + +/* Set the byte pattern used to fill gaps created by alignment. */ +extern int asm_fill (AsmScn_t *asmscn, void *bytes, size_t len); + + +/* Return ELF descriptor created for the output file of the given context. */ +extern Elf *asm_getelf (AsmCtx_t *ctx); + + +/* Return error code of last failing function call. This value is kept + separately for each thread. */ +extern int asm_errno (void); + +/* Return error string for ERROR. If ERROR is zero, return error string + for most recent error or NULL is none occurred. If ERROR is -1 the + behaviour is similar to the last case except that not NULL but a legal + string is returned. */ +extern const char *asm_errmsg (int __error); + + +/* Create context descriptor for disassembler. */ +extern DisasmCtx_t *disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb); + +/* Release descriptor for disassembler. */ +extern int disasm_end (DisasmCtx_t *ctx); + +/* Produce of disassembly output for given memory, store text in + provided buffer. */ +extern int disasm_str (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + char **bufp, size_t len, void *symcbarg); + +/* Produce disassembly output for given memory and output it using the + given callback functions. */ +extern int disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, const char *fmt, + DisasmOutputCB_t outcb, void *outcbarg, void *symcbarg); + +#ifdef __cplusplus +} +#endif + +#endif /* libasm.h */ diff --git a/libasm/libasmP.h b/libasm/libasmP.h index 54460cf..a4703fc 100644 --- a/libasm/libasmP.h +++ b/libasm/libasmP.h @@ -31,6 +31,7 @@ #include +#include "libebl.h" #include #include "libdwelf.h" diff --git a/libasm/libasmP.h.libasm-ebl b/libasm/libasmP.h.libasm-ebl new file mode 100644 index 0000000..54460cf --- /dev/null +++ b/libasm/libasmP.h.libasm-ebl @@ -0,0 +1,309 @@ +/* Internal definitions for libasm. + Copyright (C) 2002, 2004, 2005, 2016 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at + your option) any later version + + or both in parallel, as here. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see . */ + +#ifndef _LIBASMP_H +#define _LIBASMP_H 1 + +#include + +#include + +#include "libdwelf.h" + +/* gettext helper macros. */ +#define _(Str) dgettext ("elfutils", Str) + + +/* Known error codes. */ +enum + { + ASM_E_NOERROR, + ASM_E_NOMEM, /* No more memory. */ + ASM_E_CANNOT_CREATE, /* Output file cannot be created. */ + ASM_E_INVALID, /* Invalid parameters. */ + ASM_E_CANNOT_CHMOD, /* Cannot change mode of output file. */ + ASM_E_CANNOT_RENAME, /* Cannot rename output file. */ + ASM_E_DUPLSYM, /* Duplicate symbol definition. */ + ASM_E_LIBELF, /* Refer to error in libelf. */ + ASM_E_TYPE, /* Invalid section type for operation. */ + ASM_E_IOERROR, /* Error during output of data. */ + ASM_E_ENOSUP, /* No backend support. */ + ASM_E_NUM /* Keep this entry as the last. */ + }; + + +/* Special sections. */ +#define ASM_ABS_SCN ((Elf_Scn *) 1) +#define ASM_COM_SCN ((Elf_Scn *) 2) + + +/* And the hash table for symbols. */ +#include + + +/* Descriptor for a section. */ +struct AsmScn +{ + /* The underlying assembler context. */ + AsmCtx_t *ctx; + + /* Subsection ID. */ + unsigned int subsection_id; + + /* Section type. */ + GElf_Word type; + + union + { + /* Data only stored in the record for subsection zero. */ + struct + { + /* The ELF section. */ + Elf_Scn *scn; + + /* Entry in the section header string table. */ + Dwelf_Strent *strent; + + /* Next member of group. */ + struct AsmScn *next_in_group; + } main; + + /* Pointer to the record for subsection zero. */ + AsmScn_t *up; + } data; + + /* Current offset in the (sub)section. */ + GElf_Off offset; + /* Maximum alignment of the section so far. */ + GElf_Word max_align; + + /* Section content. */ + struct AsmData + { + /* Currently used number of bytes in the block. */ + size_t len; + + /* Number of bytes allocated. */ + size_t maxlen; + + /* Pointer to the next block. */ + struct AsmData *next; + + /* The actual data. */ + char data[flexarr_size]; + } *content; + + /* Fill pattern. */ + struct FillPattern + { + size_t len; + char bytes[flexarr_size]; + } *pattern; + + /* Next subsection. */ + AsmScn_t *subnext; + + /* List of all allocated sections. */ + AsmScn_t *allnext; + + /* Name of the section. */ + char name[flexarr_size]; +}; + + +/* Descriptor used for the assembling session. */ +struct AsmCtx +{ + /* File descriptor of the temporary file. */ + int fd; + + /* True if text output is wanted. */ + bool textp; + + /* Output file handle. */ + union + { + /* ELF descriptor of the temporary file. */ + Elf *elf; + /* I/O stream for text output. */ + FILE *file; + } out; + + + /* List with defined sections. */ + AsmScn_t *section_list; + /* Section header string table. */ + Dwelf_Strtab *section_strtab; + + /* Table with defined symbols. */ + asm_symbol_tab symbol_tab; + /* Number of symbols in the table. */ + unsigned int nsymbol_tab; + /* Symbol string table. */ + Dwelf_Strtab *symbol_strtab; + + /* List of section groups. */ + struct AsmScnGrp *groups; + /* Number of section groups. */ + size_t ngroups; + + /* Current required alignment for common symbols. */ + GElf_Word common_align; + + /* Lock to handle multithreaded programs. */ + rwlock_define (,lock); + + /* Counter for temporary symbols. */ + unsigned int tempsym_count; + + /* Name of the output file. */ + char *fname; + /* The name of the temporary file. */ + char tmp_fname[flexarr_size]; +}; + + +/* Descriptor for a symbol. */ +struct AsmSym +{ + /* Reference to the section which contains the symbol. */ + AsmScn_t *scn; + + /* Type of the symbol. */ + int8_t type; + /* Binding of the symbol. */ + int8_t binding; + + /* Size of the symbol. */ + GElf_Xword size; + + /* Offset in the section. */ + GElf_Off offset; + + /* Symbol table index of the symbol in the symbol table. */ + size_t symidx; + + /* Reference to name of the symbol. */ + Dwelf_Strent *strent; +}; + + +/* Descriptor for section group. */ +struct AsmScnGrp +{ + /* Entry in the section header string table. */ + Dwelf_Strent *strent; + + /* The ELF section. */ + Elf_Scn *scn; + + /* The signature. */ + struct AsmSym *signature; + + /* First member. */ + struct AsmScn *members; + /* Number of members. */ + size_t nmembers; + + /* Flags. */ + Elf32_Word flags; + + /* Next group. */ + struct AsmScnGrp *next; + + /* Name of the section group. */ + char name[flexarr_size]; +}; + + +/* Descriptor for disassembler. */ +struct DisasmCtx +{ + /* Handle for the backend library with the disassembler routine. */ + Ebl *ebl; + + /* ELF file containing all the data passed to the function. This + allows to look up symbols. */ + Elf *elf; + + /* Callback function to determine symbol names. */ + DisasmGetSymCB_t symcb; +}; + + +/* The default fill pattern: one zero byte. */ +extern const struct FillPattern *__libasm_default_pattern + attribute_hidden; + + +/* Ensure there are at least LEN bytes available in the output buffer + for ASMSCN. */ +extern int __libasm_ensure_section_space (AsmScn_t *asmscn, size_t len) + internal_function; + +/* Free all resources associated with the assembler context. */ +extern void __libasm_finictx (AsmCtx_t *ctx) internal_function; + +/* Set error code. */ +extern void __libasm_seterrno (int err) internal_function; + +/* Return handle for the named section. If it was not used before + create it. */ +extern AsmScn_t *__asm_newscn_internal (AsmCtx_t *ctx, const char *scnname, + GElf_Word type, GElf_Xword flags) + attribute_hidden; + + +/* Internal aliases of the asm_addintXX functions. */ +extern int __asm_addint8_internal (AsmScn_t *asmscn, int8_t num) + attribute_hidden; +extern int __asm_addint16_internal (AsmScn_t *asmscn, int16_t num) + attribute_hidden; +extern int __asm_addint32_internal (AsmScn_t *asmscn, int32_t num) + attribute_hidden; +extern int __asm_addint64_internal (AsmScn_t *asmscn, int64_t num) + attribute_hidden; + + +/* Produce disassembly output for given memory and output it using the + given callback functions. */ +extern int __disasm_cb_internal (DisasmCtx_t *ctx, const uint8_t **startp, + const uint8_t *end, GElf_Addr addr, + const char *fmt, DisasmOutputCB_t outcb, + void *outcbarp, void *symcbarg) + attribute_hidden; + + +/* Test whether given symbol is an internal symbol and if yes, whether + we should nevertheless emit it in the symbol table. */ +// XXX The second part should probably be controlled by an option which +// isn't implemented yet +// XXX Also, the format will change with the backend. +#define asm_emit_symbol_p(name) (strncmp (name, ".L", 2) != 0) + +#endif /* libasmP.h */ diff --git a/tests/asm-tst1.c b/tests/asm-tst1.c index 9afc676..cdf2a92 100644 --- a/tests/asm-tst1.c +++ b/tests/asm-tst1.c @@ -20,6 +20,7 @@ #endif #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst1.c.libasm-ebl b/tests/asm-tst1.c.libasm-ebl new file mode 100644 index 0000000..9afc676 --- /dev/null +++ b/tests/asm-tst1.c.libasm-ebl @@ -0,0 +1,256 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include + + +static const char fname[] = "asm-tst1-out.o"; + + +static const GElf_Ehdr expected_ehdr = + { + .e_ident = { [EI_MAG0] = ELFMAG0, + [EI_MAG1] = ELFMAG1, + [EI_MAG2] = ELFMAG2, + [EI_MAG3] = ELFMAG3, + [EI_CLASS] = ELFCLASS32, + [EI_DATA] = ELFDATA2LSB, + [EI_VERSION] = EV_CURRENT }, + .e_type = ET_REL, + .e_machine = EM_386, + .e_version = EV_CURRENT, + .e_shoff = 88, + .e_ehsize = sizeof (Elf32_Ehdr), + .e_shentsize = sizeof (Elf32_Shdr), + .e_shnum = 4, + .e_shstrndx = 3 + }; + + +static const char *scnnames[4] = + { + [0] = "", + [1] = ".text", + [2] = ".data", + [3] = ".shstrtab" + }; + + +int +main (void) +{ + AsmCtx_t *ctx; + AsmScn_t *scn1; + AsmScn_t *scn2; + int fd; + Elf *elf; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr; + int result = 0; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create two sections. */ + scn1 = asm_newscn (ctx, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR); + scn2 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + if (scn1 == NULL || scn2 == NULL) + { + printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Special alignment for the .text section. */ + if (asm_align (scn1, 32) != 0) + { + printf ("cannot align .text section: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close2; + } + + if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0) + { + puts ("ELF header does not match"); + result = 1; + goto out_close2; + } + + for (cnt = 1; cnt < 4; ++cnt) + { + Elf_Scn *scn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]) != 0) + { + printf ("section %zd's name differs: %s vs %s\n", cnt, + elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]); + result = 1; + } + + if (shdr->sh_type != (cnt == 3 ? SHT_STRTAB : SHT_PROGBITS)) + { + printf ("section %zd's type differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_EXECINSTR)) + || (cnt == 2 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) + || (cnt == 3 && shdr->sh_flags != 0)) + { + printf ("section %zd's flags differs\n", cnt); + result = 1; + } + + if (shdr->sh_addr != 0) + { + printf ("section %zd's address differs\n", cnt); + result = 1; + } + + if (shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 31) & ~31)) + { + printf ("section %zd's offset differs\n", cnt); + result = 1; + } + + if ((cnt != 3 && shdr->sh_size != 0) + || (cnt == 3 && shdr->sh_size != 23)) + { + printf ("section %zd's size differs\n", cnt); + result = 1; + } + + if (shdr->sh_link != 0) + { + printf ("section %zd's link differs\n", cnt); + result = 1; + } + + if (shdr->sh_info != 0) + { + printf ("section %zd's info differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_addralign != 32) + || (cnt != 1 && shdr->sh_addralign != 1)) + { + printf ("section %zd's addralign differs\n", cnt); + result = 1; + } + + if (shdr->sh_entsize != 0) + { + printf ("section %zd's entsize differs\n", cnt); + result = 1; + } + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst2.c b/tests/asm-tst2.c index 2556d0c..9e88b70 100644 --- a/tests/asm-tst2.c +++ b/tests/asm-tst2.c @@ -20,6 +20,7 @@ #endif #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst2.c.libasm-ebl b/tests/asm-tst2.c.libasm-ebl new file mode 100644 index 0000000..2556d0c --- /dev/null +++ b/tests/asm-tst2.c.libasm-ebl @@ -0,0 +1,278 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include + + +static const char fname[] = "asm-tst2-out.o"; + + +static const GElf_Ehdr expected_ehdr = + { + .e_ident = { [EI_MAG0] = ELFMAG0, + [EI_MAG1] = ELFMAG1, + [EI_MAG2] = ELFMAG2, + [EI_MAG3] = ELFMAG3, + [EI_CLASS] = ELFCLASS32, + [EI_DATA] = ELFDATA2LSB, + [EI_VERSION] = EV_CURRENT }, + .e_type = ET_REL, + .e_machine = EM_386, + .e_version = EV_CURRENT, + .e_shoff = 96, + .e_ehsize = sizeof (Elf32_Ehdr), + .e_shentsize = sizeof (Elf32_Shdr), + .e_shnum = 3, + .e_shstrndx = 2 + }; + + +static const char *scnnames[3] = + { + [0] = "", + [1] = ".data", + [2] = ".shstrtab" + }; + + +int +main (void) +{ + AsmCtx_t *ctx; + AsmScn_t *scn1; + AsmScn_t *scn2; + int result = 0; + int fd; + Elf *elf; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create two sections. */ + scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + scn2 = asm_newsubscn (scn1, 1); + if (scn1 == NULL || scn2 == NULL) + { + printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Special alignment for the .text section. */ + if (asm_align (scn1, 16) != 0) + { + printf ("cannot align .text section: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Add a few strings. */ + if (asm_addstrz (scn1, "one", 4) != 0) + { + printf ("cannot insert first string: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_addstrz (scn2, "three", 0) != 0) + { + printf ("cannot insert second string: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_addstrz (scn1, "two", 4) != 0) + { + printf ("cannot insert third string: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close2; + } + + if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0) + { + puts ("ELF header does not match"); + result = 1; + goto out_close2; + } + + for (cnt = 1; cnt < 3; ++cnt) + { + Elf_Scn *scn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]) != 0) + { + printf ("section %zd's name differs: %s vs %s\n", cnt, + elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]); + result = 1; + } + + if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS)) + { + printf ("section %zd's type differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) + || (cnt == 2 && shdr->sh_flags != 0)) + { + printf ("section %zd's flags differs\n", cnt); + result = 1; + } + + if (shdr->sh_addr != 0) + { + printf ("section %zd's address differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15)) + || (cnt == 2 + && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15) + + strlen ("one") + 1 + + strlen ("two") + 1 + + strlen ("three") + 1))) + { + printf ("section %zd's offset differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_size != (strlen ("one") + 1 + + strlen ("two") + 1 + + strlen ("three") + 1)) + || (cnt == 2 && shdr->sh_size != 17)) + { + printf ("section %zd's size differs\n", cnt); + result = 1; + } + + if (shdr->sh_link != 0) + { + printf ("section %zd's link differs\n", cnt); + result = 1; + } + + if (shdr->sh_info != 0) + { + printf ("section %zd's info differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_addralign != 16) + || (cnt != 1 && shdr->sh_addralign != 1)) + { + printf ("section %zd's addralign differs\n", cnt); + result = 1; + } + + if (shdr->sh_entsize != 0) + { + printf ("section %zd's entsize differs\n", cnt); + result = 1; + } + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst3.c b/tests/asm-tst3.c index e52cfbe..39c1d90 100644 --- a/tests/asm-tst3.c +++ b/tests/asm-tst3.c @@ -20,6 +20,7 @@ #endif #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst3.c.libasm-ebl b/tests/asm-tst3.c.libasm-ebl new file mode 100644 index 0000000..e52cfbe --- /dev/null +++ b/tests/asm-tst3.c.libasm-ebl @@ -0,0 +1,339 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include + + +static const char fname[] = "asm-tst3-out.o"; + + +static const char *scnnames[5] = + { + [0] = "", + [1] = ".data", + [2] = ".strtab", + [3] = ".symtab", + [4] = ".shstrtab" + }; + + +static unsigned int scntypes[5] = + { + [0] = SHT_NULL, + [1] = SHT_PROGBITS, + [2] = SHT_STRTAB, + [3] = SHT_SYMTAB, + [4] = SHT_STRTAB + }; + + +int +main (void) +{ + AsmCtx_t *ctx; + AsmScn_t *scn1; + AsmScn_t *scn2; + int result = 0; + int fd; + Elf *elf; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create two sections. */ + scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + scn2 = asm_newsubscn (scn1, 1); + if (scn1 == NULL || scn2 == NULL) + { + printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Special alignment for the .text section. */ + if (asm_align (scn1, 16) != 0) + { + printf ("cannot align .text section: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Add a few strings with names. */ + if (asm_newsym (scn1, "one", 4, STT_OBJECT, STB_GLOBAL) == NULL) + { + printf ("cannot create first name: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_addstrz (scn1, "one", 4) != 0) + { + printf ("cannot insert first string: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_newsym (scn2, "three", 6, STT_OBJECT, STB_WEAK) == NULL) + { + printf ("cannot create second name: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_addstrz (scn2, "three", 0) != 0) + { + printf ("cannot insert second string: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_newsym (scn1, "two", 4, STT_OBJECT, STB_LOCAL) == NULL) + { + printf ("cannot create third name: %s\n", asm_errmsg (-1)); + result = 1; + } + if (asm_addstrz (scn1, "two", 4) != 0) + { + printf ("cannot insert third string: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close2; + } + + for (cnt = 1; cnt < 5; ++cnt) + { + Elf_Scn *scn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]) != 0) + { + printf ("section %zd's name differs: %s vs %s\n", cnt, + elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]); + result = 1; + } + + if (shdr->sh_type != scntypes[cnt]) + { + printf ("section %zd's type differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) + || (cnt != 1 && shdr->sh_flags != 0)) + { + printf ("section %zd's flags differs\n", cnt); + result = 1; + } + + if (shdr->sh_addr != 0) + { + printf ("section %zd's address differs\n", cnt); + result = 1; + } + + if (cnt == 3) + { + Elf_Data *data; + + if (shdr->sh_link != 2) + { + puts ("symbol table has incorrect link"); + result = 1; + } + + data = elf_getdata (scn, NULL); + if (data == NULL) + { + puts ("cannot get data of symbol table"); + result = 1; + } + else + { + size_t inner; + + for (inner = 1; + inner < (shdr->sh_size + / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT)); + ++inner) + { + GElf_Sym sym_mem; + GElf_Sym *sym; + + sym = gelf_getsym (data, inner, &sym_mem); + if (sym == NULL) + { + printf ("cannot get symbol %zu: %s\n", + inner, elf_errmsg (-1)); + result = 1; + } + else + { + /* The order of the third and fourth entry depends + on how the hash table is organized. */ + static const char *names[4] = + { + [0] = "", + [1] = "two", + [2] = "one", + [3] = "three" + }; + static const int info[4] = + { + [0] = GELF_ST_INFO (STB_LOCAL, STT_NOTYPE), + [1] = GELF_ST_INFO (STB_LOCAL, STT_OBJECT), + [2] = GELF_ST_INFO (STB_GLOBAL, STT_OBJECT), + [3] = GELF_ST_INFO (STB_WEAK, STT_OBJECT) + }; + static const unsigned value[4] = + { + [0] = 0, + [1] = 4, + [2] = 0, + [3] = 8 + }; + + if (strcmp (names[inner], + elf_strptr (elf, shdr->sh_link, + sym->st_name)) != 0) + { + printf ("symbol %zu has different name\n", inner); + result = 1; + } + + if (sym->st_value != value[inner]) + { + printf ("symbol %zu has wrong value\n", inner); + result = 1; + } + + if (sym->st_other != 0) + { + printf ("symbol %zu has wrong other info\n", inner); + result = 1; + } + + if (sym->st_shndx != 1) + { + printf ("symbol %zu has wrong section reference\n", + inner); + result = 1; + } + + if (sym->st_info != info[inner]) + { + printf ("symbol %zu has wrong type or binding\n", + inner); + result = 1; + } + + if ((inner != 3 && sym->st_size != 4) + || (inner == 3 && sym->st_size != 6)) + { + printf ("symbol %zu has wrong size\n", inner); + result = 1; + } + } + } + } + } + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst4.c b/tests/asm-tst4.c index 52e9e20..5114938 100644 --- a/tests/asm-tst4.c +++ b/tests/asm-tst4.c @@ -20,6 +20,7 @@ #endif #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst4.c.libasm-ebl b/tests/asm-tst4.c.libasm-ebl new file mode 100644 index 0000000..52e9e20 --- /dev/null +++ b/tests/asm-tst4.c.libasm-ebl @@ -0,0 +1,104 @@ +/* Copyright (C) 2002-2012 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include +#include +#include + + +static const char fname[] = "asm-tst4-out.o"; + + +int +main (void) +{ + AsmCtx_t *ctx; + int result = 0; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create 66000 sections. */ + for (cnt = 0; cnt < 66000; ++cnt) + { + char buf[20]; + AsmScn_t *scn; + + /* Create a unique name. */ + snprintf (buf, sizeof (buf), ".data.%zu", cnt); + + /* Create the section. */ + scn = asm_newscn (ctx, buf, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + if (scn == NULL) + { + printf ("cannot create section \"%s\" in output file: %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add some content. */ + if (asm_adduint32 (scn, cnt) != 0) + { + printf ("cannot create content of section \"%s\": %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + if (result == 0) + result = WEXITSTATUS (system ("../src/elflint -q asm-tst4-out.o")); + + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst5.c b/tests/asm-tst5.c index 5a29b01..dcb852f 100644 --- a/tests/asm-tst5.c +++ b/tests/asm-tst5.c @@ -20,6 +20,7 @@ #endif #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst5.c.libasm-ebl b/tests/asm-tst5.c.libasm-ebl new file mode 100644 index 0000000..5a29b01 --- /dev/null +++ b/tests/asm-tst5.c.libasm-ebl @@ -0,0 +1,116 @@ +/* Copyright (C) 2002-2012 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include +#include +#include + +#include "system.h" + + +static const char fname[] = "asm-tst5-out.o"; + + +int +main (void) +{ + AsmCtx_t *ctx; + int result = 0; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create 66000 sections. */ + for (cnt = 0; cnt < 66000; ++cnt) + { + char buf[20]; + AsmScn_t *scn; + + /* Create a unique name. */ + snprintf (buf, sizeof (buf), ".data.%zu", cnt); + + /* Create the section. */ + scn = asm_newscn (ctx, buf, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + if (scn == NULL) + { + printf ("cannot create section \"%s\" in output file: %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add a name. */ + snprintf (buf, sizeof (buf), "%zu", cnt); + if (asm_newsym (scn, buf, sizeof (uint32_t), STT_OBJECT, + STB_GLOBAL) == NULL) + { + printf ("cannot create symbol \"%s\": %s\n", buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add some content. */ + if (asm_adduint32 (scn, cnt) != 0) + { + printf ("cannot create content of section \"%s\": %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + if (result == 0) + result = WEXITSTATUS (system ("../src/elflint -q asm-tst5-out.o")); + + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst6.c b/tests/asm-tst6.c index bd9b362..829cd90 100644 --- a/tests/asm-tst6.c +++ b/tests/asm-tst6.c @@ -19,6 +19,7 @@ # include #endif +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst6.c.libasm-ebl b/tests/asm-tst6.c.libasm-ebl new file mode 100644 index 0000000..bd9b362 --- /dev/null +++ b/tests/asm-tst6.c.libasm-ebl @@ -0,0 +1,150 @@ +/* Copyright (C) 2002-2012 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include +#include + +#include + + +static const char fname[] = "asm-tst6-out.o"; + + +int +main (void) +{ + AsmCtx_t *ctx; + int result = 0; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + for (cnt = 0; cnt < 22000; ++cnt) + { + char buf[512]; + AsmScnGrp_t *grp; + AsmScn_t *scn; + AsmSym_t *sym; + + snprintf (buf, sizeof (buf), ".grp%zu", cnt); + grp = asm_newscngrp (ctx, buf, NULL, 0); + if (grp == NULL) + { + printf ("cannot section group %zu: %s\n", cnt, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + scn = asm_newscn_ingrp (ctx, ".data", SHT_PROGBITS, + SHF_ALLOC | SHF_WRITE, grp); + if (scn == NULL) + { + printf ("cannot data section for group %zu: %s\n", + cnt, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add a name. */ + snprintf (buf, sizeof (buf), "%zu", cnt); + sym = asm_newsym (scn, buf, sizeof (uint32_t), STT_OBJECT, + STB_GLOBAL); + if (sym == NULL) + { + printf ("cannot create symbol \"%s\": %s\n", buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add some content. */ + if (asm_adduint32 (scn, cnt) != 0) + { + printf ("cannot create content of section \"%s\": %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Now we have a symbol, use it as the signature. */ + if (asm_scngrp_newsignature (grp, sym) != 0) + { + printf ("cannot set signature for section group %zu: %s\n", + cnt, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Create a phony debug info section. */ + scn = asm_newscn_ingrp (ctx, ".stab", SHT_PROGBITS, 0, grp); + if (scn == NULL) + { + printf ("cannot stab section for group %zu: %s\n", + cnt, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Add some content. */ + if (asm_adduint32 (scn, cnt) != 0) + { + printf ("cannot create content of section \"%s\": %s\n", + buf, asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + if (result == 0) + result = WEXITSTATUS (system ("../src/elflint -q asm-tst6-out.o")); + + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst7.c b/tests/asm-tst7.c index 00cb2bf..9017976 100644 --- a/tests/asm-tst7.c +++ b/tests/asm-tst7.c @@ -21,6 +21,7 @@ #include #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst7.c.libasm-ebl b/tests/asm-tst7.c.libasm-ebl new file mode 100644 index 0000000..00cb2bf --- /dev/null +++ b/tests/asm-tst7.c.libasm-ebl @@ -0,0 +1,181 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include + + +static const char fname[] = "asm-tst7-out.o"; + + +int +main (void) +{ + int result = 0; + size_t cnt; + AsmCtx_t *ctx; + Elf *elf; + int fd; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + if (asm_newcomsym (ctx, "commsym", 4, 16) == NULL) + { + printf ("cannot create common symbol: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + for (cnt = 1; 1; ++cnt) + { + Elf_Scn *scn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + /* We are looking for the symbol table. */ + if (shdr->sh_type != SHT_SYMTAB) + continue; + + for (cnt = 1; cnt< (shdr->sh_size + / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT)); + ++cnt) + { + GElf_Sym sym_mem; + GElf_Sym *sym; + + if (cnt > 1) + { + puts ("too many symbol"); + result = 1; + break; + } + + sym = gelf_getsym (elf_getdata (scn, NULL), cnt, &sym_mem); + if (sym == NULL) + { + printf ("cannot get symbol %zu: %s\n", cnt, elf_errmsg (-1)); + result = 1; + } + else + { + if (sym->st_shndx != SHN_COMMON) + { + printf ("expected common symbol, got section %u\n", + (unsigned int) sym->st_shndx); + result = 1; + } + + if (sym->st_value != 16) + { + printf ("requested alignment 16, is %" PRIuMAX "\n", + (uintmax_t) sym->st_value); + result = 1; + } + + if (sym->st_size != 4) + { + printf ("requested size 4, is %" PRIuMAX "\n", + (uintmax_t) sym->st_value); + result = 1; + } + } + } + + break; + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst8.c b/tests/asm-tst8.c index 4fb0d99..a65509f 100644 --- a/tests/asm-tst8.c +++ b/tests/asm-tst8.c @@ -21,6 +21,7 @@ #include #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst8.c.libasm-ebl b/tests/asm-tst8.c.libasm-ebl new file mode 100644 index 0000000..4fb0d99 --- /dev/null +++ b/tests/asm-tst8.c.libasm-ebl @@ -0,0 +1,189 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include + + +static const char fname[] = "asm-tst8-out.o"; + + +int +main (void) +{ + int result = 0; + size_t cnt; + AsmCtx_t *ctx; + Elf *elf; + int fd; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + if (asm_newabssym (ctx, "tst8-out.s", 4, 0xfeedbeef, STT_FILE, STB_LOCAL) + == NULL) + { + printf ("cannot create absolute symbol: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + for (cnt = 1; 1; ++cnt) + { + Elf_Scn *scn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + scn = elf_getscn (elf, cnt); + if (scn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (scn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + /* We are looking for the symbol table. */ + if (shdr->sh_type != SHT_SYMTAB) + continue; + + for (cnt = 1; cnt< (shdr->sh_size + / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT)); + ++cnt) + { + GElf_Sym sym_mem; + GElf_Sym *sym; + + if (cnt > 1) + { + puts ("too many symbol"); + result = 1; + break; + } + + sym = gelf_getsym (elf_getdata (scn, NULL), cnt, &sym_mem); + if (sym == NULL) + { + printf ("cannot get symbol %zu: %s\n", cnt, elf_errmsg (-1)); + result = 1; + } + else + { + if (sym->st_shndx != SHN_ABS) + { + printf ("expected common symbol, got section %u\n", + (unsigned int) sym->st_shndx); + result = 1; + } + + if (sym->st_value != 0xfeedbeef) + { + printf ("requested value 0xfeedbeef, is %#" PRIxMAX "\n", + (uintmax_t) sym->st_value); + result = 1; + } + + if (sym->st_size != 4) + { + printf ("requested size 4, is %" PRIuMAX "\n", + (uintmax_t) sym->st_value); + result = 1; + } + + if (GELF_ST_TYPE (sym->st_info) != STT_FILE) + { + printf ("requested type FILE, is %u\n", + (unsigned int) GELF_ST_TYPE (sym->st_info)); + result = 1; + } + } + } + + break; + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +} diff --git a/tests/asm-tst9.c b/tests/asm-tst9.c index b6d0e43..681e872 100644 --- a/tests/asm-tst9.c +++ b/tests/asm-tst9.c @@ -21,6 +21,7 @@ #include #include +#include ELFUTILS_HEADER(ebl) #include ELFUTILS_HEADER(asm) #include #include diff --git a/tests/asm-tst9.c.libasm-ebl b/tests/asm-tst9.c.libasm-ebl new file mode 100644 index 0000000..b6d0e43 --- /dev/null +++ b/tests/asm-tst9.c.libasm-ebl @@ -0,0 +1,335 @@ +/* Copyright (C) 2002-2010 Red Hat, Inc. + This file is part of elfutils. + Written by Ulrich Drepper , 2002. + + This file is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + elfutils is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include ELFUTILS_HEADER(asm) +#include +#include +#include +#include + + +static const char fname[] = "asm-tst9-out.o"; + + +static int32_t input[] = + { + 0, 1, 129, 510, 2000, 33000, 0x7ffffff, 0x7fffffff + }; +#define ninput (sizeof (input) / sizeof (input[0])) + + +static const GElf_Ehdr expected_ehdr = + { + .e_ident = { [EI_MAG0] = ELFMAG0, + [EI_MAG1] = ELFMAG1, + [EI_MAG2] = ELFMAG2, + [EI_MAG3] = ELFMAG3, + [EI_CLASS] = ELFCLASS32, + [EI_DATA] = ELFDATA2LSB, + [EI_VERSION] = EV_CURRENT }, + .e_type = ET_REL, + .e_machine = EM_386, + .e_version = EV_CURRENT, + .e_shoff = 180, + .e_ehsize = sizeof (Elf32_Ehdr), + .e_shentsize = sizeof (Elf32_Shdr), + .e_shnum = 3, + .e_shstrndx = 2 + }; + + +static const char *scnnames[3] = + { + [0] = "", + [1] = ".data", + [2] = ".shstrtab" + }; + + +static const char expecteddata[] = + { + 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7f, + 0x81, 0x01, 0x81, 0x01, 0xff, 0xfe, 0xff, 0xff, 0x0f, 0xff, 0x7e, 0xfe, + 0x03, 0xfe, 0x03, 0x82, 0xfc, 0xff, 0xff, 0x0f, 0x82, 0x7c, 0xd0, 0x0f, + 0xd0, 0x0f, 0xb0, 0xf0, 0xff, 0xff, 0x0f, 0xb0, 0x70, 0xe8, 0x81, 0x02, + 0xe8, 0x81, 0x02, 0x98, 0xfe, 0xfd, 0xff, 0x0f, 0x98, 0xfe, 0x7d, 0xff, + 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0x81, 0x80, 0x80, 0xc0, 0x0f, + 0x81, 0x80, 0x80, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, + 0xff, 0x07, 0x81, 0x80, 0x80, 0x80, 0x08, 0x81, 0x80, 0x80, 0x80, 0x78 + }; + + +int +main (void) +{ + AsmCtx_t *ctx; + AsmScn_t *scn; + int result = 0; + int fd; + Elf *elf; + GElf_Ehdr ehdr_mem; + GElf_Ehdr *ehdr; + size_t cnt; + + elf_version (EV_CURRENT); + + Ebl *ebl = ebl_openbackend_machine (EM_386); + if (ebl == NULL) + { + puts ("cannot open backend library"); + return 1; + } + + ctx = asm_begin (fname, ebl, false); + if (ctx == NULL) + { + printf ("cannot create assembler context: %s\n", asm_errmsg (-1)); + return 1; + } + + /* Create two sections. */ + scn = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE); + if (scn == NULL) + { + printf ("cannot create section in output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Special alignment for the .text section. */ + if (asm_align (scn, 16) != 0) + { + printf ("cannot align .text section: %s\n", asm_errmsg (-1)); + result = 1; + } + + /* Add a few ULEB128 and SLEB128 numbers. */ + for (cnt = 0; cnt < ninput; ++cnt) + { + if (asm_adduleb128 (scn, input[cnt]) != 0) + { + printf ("cannot insert uleb %" PRIu32 ": %s\n", + (uint32_t) input[cnt], asm_errmsg (-1)); + result = 1; + } + + if (asm_addsleb128 (scn, input[cnt]) != 0) + { + printf ("cannot insert sleb %" PRId32 ": %s\n", + input[cnt], asm_errmsg (-1)); + result = 1; + } + + if (asm_adduleb128 (scn, -input[cnt]) != 0) + { + printf ("cannot insert uleb %" PRIu32 ": %s\n", + (uint32_t) -input[cnt], asm_errmsg (-1)); + result = 1; + } + + if (asm_addsleb128 (scn, -input[cnt]) != 0) + { + printf ("cannot insert sleb %" PRId32 ": %s\n", + -input[cnt], asm_errmsg (-1)); + result = 1; + } + } + + /* Create the output file. */ + if (asm_end (ctx) != 0) + { + printf ("cannot create output file: %s\n", asm_errmsg (-1)); + asm_abort (ctx); + return 1; + } + + /* Check the file. */ + fd = open (fname, O_RDONLY); + if (fd == -1) + { + printf ("cannot open generated file: %m\n"); + result = 1; + goto out; + } + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close; + } + if (elf_kind (elf) != ELF_K_ELF) + { + puts ("not a valid ELF file"); + result = 1; + goto out_close2; + } + + ehdr = gelf_getehdr (elf, &ehdr_mem); + if (ehdr == NULL) + { + printf ("cannot get ELF header: %s\n", elf_errmsg (-1)); + result = 1; + goto out_close2; + } + + if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0) + { + puts ("ELF header does not match"); + result = 1; + goto out_close2; + } + + for (cnt = 1; cnt < 3; ++cnt) + { + Elf_Scn *escn; + GElf_Shdr shdr_mem; + GElf_Shdr *shdr; + + escn = elf_getscn (elf, cnt); + if (escn == NULL) + { + printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + shdr = gelf_getshdr (escn, &shdr_mem); + if (shdr == NULL) + { + printf ("cannot get section header for section %zd: %s\n", + cnt, elf_errmsg (-1)); + result = 1; + continue; + } + + if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]) != 0) + { + printf ("section %zd's name differs: %s vs %s\n", cnt, + elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name), + scnnames[cnt]); + result = 1; + } + + if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS)) + { + printf ("section %zd's type differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE)) + || (cnt == 2 && shdr->sh_flags != 0)) + { + printf ("section %zd's flags differs\n", cnt); + result = 1; + } + + if (shdr->sh_addr != 0) + { + printf ("section %zd's address differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15)) + || (cnt == 2 + && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15) + + sizeof (expecteddata)))) + { + printf ("section %zd's offset differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_size != sizeof (expecteddata)) + || (cnt == 2 && shdr->sh_size != 17)) + { + printf ("section %zd's size differs\n", cnt); + result = 1; + } + + if (shdr->sh_link != 0) + { + printf ("section %zd's link differs\n", cnt); + result = 1; + } + + if (shdr->sh_info != 0) + { + printf ("section %zd's info differs\n", cnt); + result = 1; + } + + if ((cnt == 1 && shdr->sh_addralign != 16) + || (cnt != 1 && shdr->sh_addralign != 1)) + { + printf ("section %zd's addralign differs\n", cnt); + result = 1; + } + + if (shdr->sh_entsize != 0) + { + printf ("section %zd's entsize differs\n", cnt); + result = 1; + } + + if (cnt == 1) + { + Elf_Data *data = elf_getdata (escn, NULL); + + if (data == NULL) + { + printf ("cannot get data of section %zd\n", cnt); + result = 1; + } + else + { + if (data->d_size != sizeof (expecteddata)) + { + printf ("data block size of section %zd wrong: got %zd, " + "expected 96\n", cnt, data->d_size); + result = 1; + } + + if (memcmp (data->d_buf, expecteddata, sizeof (expecteddata)) + != 0) + { + printf ("data block content of section %zd wrong\n", cnt); + result = 1; + } + } + } + } + + out_close2: + elf_end (elf); + out_close: + close (fd); + out: + /* We don't need the file anymore. */ + unlink (fname); + + ebl_closebackend (ebl); + + return result; +}