From patchwork Mon Oct 23 03:32:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rishi Raj X-Patchwork-Id: 156658 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:ce89:0:b0:403:3b70:6f57 with SMTP id p9csp1054545vqx; Sun, 22 Oct 2023 20:33:23 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGpRQmg9ALyFdYSbwd5YmmijeUD8BKjz8N9QKcl6JoK09V9GcNfxIONMw1B9eQLQIIL1QiI X-Received: by 2002:a05:620a:2805:b0:771:532:31f4 with SMTP id f5-20020a05620a280500b00771053231f4mr7236066qkp.43.1698032002983; Sun, 22 Oct 2023 20:33:22 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1698032002; cv=pass; d=google.com; s=arc-20160816; b=eZ22dngbmU8S/VUPJ29PdTLoREBjUtIjEWZJ5zZO6ZYa9ghqltnEVgUGPwnZ3902Vy 9n2LOYSefsUga7N3/1eNJldP66akIJuYgK48d4gP1a8ZSUNKCVkAohYbKW7AnluVTNFf YsUlx1X2TGq6gpHqf5QMbKTzO+97rFNM7bymC/2qL5FnZTT5lenQ8QAf9EPf5Y7+WAo6 eXHXHrhOF41bZrcEmJ1AXL0w7U2ImLOb2FDP4UM1y8/SHmYk8NqilDK+7FOc/uXvZ3gv seXRifs6TX9IrjyfJN3yy+zMOiiVfPqn8qE+k8IE5aAypBrsxfpeGUDLugTCEfgvgCPr e7KQ== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:to:subject:message-id:date:from :mime-version:dkim-signature:arc-filter:dmarc-filter:delivered-to; bh=7BllmRMIVQhECIuIlCpajpkoMM+LIU/ifNYWdqLWYRE=; fh=NbV1+M4TEF5HMrl3sDBgyPBwUgmsY4rT0U1EHTtjqLQ=; b=mvhX0EWkX34h1eLwh8rI0HqyP2VJ/qs6BnuyxqHXpEfP5+X4zNdcYcWZjankyIljj8 k16ByN66coA+nt3+TYD2G/T77kFL1jHQbh1SzNxqAOBRjt97+TNYOYl7/HxfluvFBtSF E24L01N2gGSOYjQyuxibmWupYshCZ2XpSqGWBjx4Xfuig8cTsu7RvI8uoWMTzKhMSICt tngxlNJpCIF9jVOinlEvDkcelsaVXd0MD9/HKSG/AQs/2p0zvB/qr2qzhtKuEkCP8Thv cgiZD07HDBVhe9gNRb1PSbBeyH6/rGjpyH0+Hev4yE+eqG/LZt7eHQjfhV7cw4QQNRpj XbvQ== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=IyzrueoF; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (server2.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id w18-20020a05620a425200b007740ea0f465si5028411qko.355.2023.10.22.20.33.22 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 22 Oct 2023 20:33:22 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gmail.com header.s=20230601 header.b=IyzrueoF; arc=pass (i=1); spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id B74F63858431 for ; Mon, 23 Oct 2023 03:33:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oi1-x22a.google.com (mail-oi1-x22a.google.com [IPv6:2607:f8b0:4864:20::22a]) by sourceware.org (Postfix) with ESMTPS id 95B4F3858C52 for ; Mon, 23 Oct 2023 03:32:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 95B4F3858C52 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 95B4F3858C52 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=2607:f8b0:4864:20::22a ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698031979; cv=none; b=VaPEd1h5Y7qWS+yYSeKEsUu5lZuA7oMz7BskTUorcr97zq7vOzmJwhbl2wBsZf7DiKmLmFF06lJNxC8xn8F0Ga2rw19wd+zmsk7+L8ENhQSClfzzG057kXj56MxksPOaWUjy00IHuItLB8IruYj84jYoNsCktAQLL7MKY56EPzY= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1698031979; c=relaxed/simple; bh=I0OG2rR7pg4DLspYElj5s07NYCS0+jVFXnLLN8UuJcA=; h=DKIM-Signature:MIME-Version:From:Date:Message-ID:Subject:To; b=pDFgW1mRGyA4IPmfspclUf4Ncd8g3QUyt3ecNY6mLF4dNQFnXaMqPmlQzmePvrkBy0cDdAbWYRHwlUEm9wX7M1mSuWip0IRaE764Mky9MBSCTbdOSvlpNJY09WkTP9auY/Un3lg59PCaWhCTSl8lg0YQ7Qrh68a5iJDm0fE4oG4= ARC-Authentication-Results: i=1; server2.sourceware.org Received: by mail-oi1-x22a.google.com with SMTP id 5614622812f47-3b4145e887bso140771b6e.3 for ; Sun, 22 Oct 2023 20:32:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1698031974; x=1698636774; darn=gcc.gnu.org; h=to:subject:message-id:date:from:mime-version:from:to:cc:subject :date:message-id:reply-to; bh=7BllmRMIVQhECIuIlCpajpkoMM+LIU/ifNYWdqLWYRE=; b=IyzrueoFH4vXFIVC9lTtMQiZmXgvZm1OfeYCj196fwDgjNlYfXYgUrXXfDAznScniY e92Rkzg44wTfKqL+o0IT06c5KxpvAuDbOTl3XOzQ9+GGjmN7X39fXBoLdMUA0X/BEdPv ZqDaVo6+Pb5axwdy4H90/dPTeowTGus4hM3jybw7akOJY/Y76d8yUTqoZL16S0RU8Z6Y bbkfe4Aro1a6O/7705qAXEI6NqleYX2JW5b5TgRJN0ofLe701zawdh0lGNQihS8UcQoR GY/SQ6IkVpRSOKx5kaDDjwwMceDL80m1bv08Kwwr/Mtm9PjRicyJV3FAYUIfnJ4XUrYa CRFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1698031974; x=1698636774; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=7BllmRMIVQhECIuIlCpajpkoMM+LIU/ifNYWdqLWYRE=; b=fjgtXhvz9AAj8jjQaWeNQR9vIceT0rw/DTftHj3SMrrurMH9X1egeY+5H9whV+vpf0 2rrDobUnzMafYQGefmkXZ239uXrAbSGuUoQJ0dhU13YuG5Kc8nuHHZAbELqy4Gn95lKT oCAyMWydnuZXX0Xr2a7NXQ6rxkPMb8MpXlxfQNWT7DqLf8u0LPBKd2BeAW03yUGR0axH FQbr63R+yLwteQzm+ygvFw8qK/sWIlrBXhtCr8T289ItIlwum1WMrmdhp5Dqj8EzbHEP iX093QBOCok9DeGmYCXM3zXHo7uxkryyRK8MfzktKqH9yjH0jFvtyoTlm3bu1hmFDwe4 KmAA== X-Gm-Message-State: AOJu0YzdAtL++/0pcMcygigX+WbH0QM42mNjrzWrKoFw6ncruE7D8xc3 xeAps5Jn30XO8AZ4kDZbANuSEXxTxg7KB/5Mzx1BOm+uaX7txA== X-Received: by 2002:a05:6808:181b:b0:3af:6634:49d0 with SMTP id bh27-20020a056808181b00b003af663449d0mr9282819oib.18.1698031973678; Sun, 22 Oct 2023 20:32:53 -0700 (PDT) MIME-Version: 1.0 From: Rishi Raj Date: Mon, 23 Oct 2023 09:02:42 +0530 Message-ID: Subject: [PATCH][WIP] libiberty: Support for relocation output To: gcc-patches@gcc.gnu.org, Jan Hubicka , Martin Jambor X-Spam-Status: No, score=-6.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, GIT_PATCH_0, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1780515605497895085 X-GMAIL-MSGID: 1780515605497895085 This patch teaches libiberty to output X86-64 Relocations. From d3b2d168369e76a6fac2b3b3cbd591ccf22ea8ea Mon Sep 17 00:00:00 2001 From: Rishi Raj Date: Mon, 23 Oct 2023 06:22:44 +0530 Subject: [PATCH 1/3] Extended libiberty to output X86_64 relocations Signed-off-by: Rishi Raj --- include/simple-object.h | 11 +- libiberty/simple-object-common.h | 28 ++- libiberty/simple-object-elf.c | 317 ++++++++++++++++++++++++++----- libiberty/simple-object.c | 95 +++++++-- 4 files changed, 387 insertions(+), 64 deletions(-) { @@ -532,6 +534,60 @@ simple_object_write_add_data (simple_object_write *sobj ATTRIBUTE_UNUSED, return NULL; } +/* Add relocation to a section. */ + +void +simple_object_write_add_relocation (simple_object_write_section *section, + unsigned long offset, long addend, const char *name, unsigned long rel_sec_idx) +{ + struct simple_object_write_section_relocation *wsr; + + wsr = XNEW (struct simple_object_write_section_relocation); + wsr->next = NULL; + wsr->offset = offset; + wsr->addend = addend; + wsr->name = name; + wsr->rel_sec_idx = rel_sec_idx; + + if (section->last_relocation == NULL) + { + section->relocations = wsr; + section->last_relocation = wsr; + } + else + { + section->last_relocation->next = wsr; + section->last_relocation = wsr; + } + +} + +void simple_object_modify_buffer (simple_object_write_section *section, + unsigned long offset, unsigned char *buffer, int copy) +{ + struct simple_object_write_section_buffer *wsb; + unsigned long curr_offset = 0; + for(wsb = section->buffers; wsb != NULL; wsb=wsb->next) + { + if(offset == curr_offset) + { + if (!copy) + { + wsb->buffer = buffer; + wsb->free_buffer = NULL; + } + else + { + wsb->free_buffer = (void *) XNEWVEC (char, wsb->size); + memcpy (wsb->free_buffer, buffer, wsb->size); + wsb->buffer = wsb->free_buffer; + } + } + curr_offset+=wsb->size; + } + +} + /* Write the complete object file. */ const char * @@ -540,26 +596,32 @@ simple_object_write_to_file (simple_object_write *sobj, int descriptor, { return sobj->functions->write_to_file (sobj, descriptor, err); } -/*Adds a symbol in to common*/ +/* Adds a symbol to .symtab. If shndx is -1 add it to COMMON */ void -simple_object_write_add_symbol(simple_object_write *sobj, const char *name, -size_t size, unsigned int align) +simple_object_write_add_symbol(simple_object_write *sobj, + const char *name, unsigned int value, + size_t size, unsigned char bind, + unsigned char type, unsigned short int shndx, unsigned char st_other) { simple_object_symbol *symbol; - symbol=XNEW(simple_object_symbol); - symbol->next=NULL; - symbol->name=xstrdup(name); - symbol->align=align; - symbol->size=size; + symbol = XNEW(simple_object_symbol); + symbol->next = NULL; + symbol->name = xstrdup(name); + symbol->value = value; + symbol->size = size; + symbol->bind = bind; + symbol->type = type; + symbol->shndx = shndx; + symbol->st_other = st_other; if(sobj->last_symbol==NULL) { - sobj->symbols=symbol; - sobj->last_symbol=symbol; + sobj->symbols = symbol; + sobj->last_symbol = symbol; } else { - sobj->last_symbol->next=symbol; - sobj->last_symbol=symbol; + sobj->last_symbol->next = symbol; + sobj->last_symbol = symbol; } } @@ -576,6 +638,7 @@ simple_object_release_write (simple_object_write *sobj) while (section != NULL) { struct simple_object_write_section_buffer *buffer; + struct simple_object_write_section_relocation *relocation; simple_object_write_section *next_section; buffer = section->buffers; @@ -589,6 +652,14 @@ simple_object_release_write (simple_object_write *sobj) XDELETE (buffer); buffer = next_buffer; } + while (relocation != NULL) + { + struct simple_object_write_section_relocation *next_relocation; + + next_relocation = relocation->next; + XDELETE (relocation); + relocation = next_relocation; + } next_section = section->next; free (section->name); diff --git a/include/simple-object.h b/include/simple-object.h index 3a14184b12c..17ecd856636 100644 --- a/include/simple-object.h +++ b/include/simple-object.h @@ -186,6 +186,14 @@ simple_object_write_add_data (simple_object_write *simple_object, simple_object_write_section *section, const void *buffer, size_t size, int copy, int *err); +/* Add relocation to SECTION in SIMPLE_OBJECT */ +void +simple_object_write_add_relocation (simple_object_write_section *section, + unsigned long offset, long addend, const char *name, unsigned long rel_sec_idx); + +/* Modifies simple object section buffer at offset. */ +void simple_object_modify_buffer (simple_object_write_section *section, + unsigned long offset, unsigned char *buffer, int copy); /* Write the complete object file to DESCRIPTOR, an open file descriptor. This returns NULL on success. On error this returns @@ -199,7 +207,8 @@ simple_object_write_to_file (simple_object_write *simple_object, object_write_to_file function*/ extern void simple_object_write_add_symbol(simple_object_write *sobj, const char *name, -size_t size, unsigned int align); + unsigned int value, size_t size, unsigned char bind, + unsigned char type, unsigned short int shndx, unsigned char st_other); /* Release all resources associated with SIMPLE_OBJECT, including any simple_object_write_section's that may have been created. */ diff --git a/libiberty/simple-object-common.h b/libiberty/simple-object-common.h index df99c9d85ac..1dc06908eec 100644 --- a/libiberty/simple-object-common.h +++ b/libiberty/simple-object-common.h @@ -73,9 +73,17 @@ struct simple_object_symbol_struct /*The name of this symbol. */ char *name; /* Symbol value */ - unsigned int align; + unsigned int value; /* Symbol size */ size_t size; + /*Symbol binding*/ + unsigned char bind; + /*Symbol info*/ + unsigned char type; + /*Symbol section index*/ + unsigned short int shndx; + /* Symbol visibility */ + unsigned char st_other; }; /* A section in an object file being created. */ @@ -93,6 +101,11 @@ struct simple_object_write_section_struct struct simple_object_write_section_buffer *buffers; /* The last data attached to this section. */ struct simple_object_write_section_buffer *last_buffer; + /*The first relocation attached to this section. */ + struct simple_object_write_section_relocation *relocations; + /* The last relocation attache to this section. */ + struct simple_object_write_section_relocation *last_relocation; + }; /* Data attached to a section. */ @@ -108,6 +121,19 @@ struct simple_object_write_section_buffer /* A buffer to free, or NULL. */ void *free_buffer; }; +struct simple_object_write_section_relocation +{ + /* The next relocation for this section. */ + struct simple_object_write_section_relocation *next; + /* The offset. */ + unsigned long offset; + /* Addend */ + long addend; + /* Relocation symbol */ + const char *name; + /* Relocation symbol st_shndx wrt .debug_info index */ + unsigned long rel_sec_idx; +}; /* The number of bytes we read from the start of the file to pass to the match function. */ diff --git a/libiberty/simple-object-elf.c b/libiberty/simple-object-elf.c index 86b7a27dc74..0bbaf4b489f 100644 --- a/libiberty/simple-object-elf.c +++ b/libiberty/simple-object-elf.c @@ -238,6 +238,7 @@ typedef struct #define STT_NOTYPE 0 /* Symbol type is unspecified */ #define STT_OBJECT 1 /* Symbol is a data object */ #define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol is associate with a section */ #define STT_TLS 6 /* Thread local data object */ #define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */ @@ -248,6 +249,63 @@ typedef struct #define STV_DEFAULT 0 /* Visibility is specified by binding type */ #define STV_HIDDEN 2 /* Can only be seen inside currect component */ +typedef struct +{ + unsigned char r_offset[4]; /* Address */ + unsigned char r_info[4]; /* relocation type and symbol index */ +} Elf32_External_Rel; + +typedef struct +{ + unsigned char r_offset[8]; /* Address */ + unsigned char r_info[8]; /* Relocation type and symbol index */ +} Elf64_External_Rel; +typedef struct +{ + unsigned char r_offset[4]; /* Address */ + unsigned char r_info[4]; /* Relocation type and symbol index */ + char r_addend[4]; /* Addend */ +} Elf32_External_Rela; +typedef struct +{ + unsigned char r_offset[8]; /* Address */ + unsigned char r_info[8]; /* Relocation type and symbol index */ + unsigned char r_addend[8]; /* Addend */ +} Elf64_External_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((unsigned long) (sym)) << 32) + (type)) + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ + +/* Index into relocation symbol array */ +#define DEBUG_INFO_IDX 0 +#define DEBUG_ABBREV_IDX 1 +#define DEBUG_STR_IDX 2 +#define DEBUG_LINE_IDX 3 +#define DEBUG_LINE_STR_IDX 4 + /* Functions to fetch and store different ELF types, depending on the endianness and size. */ @@ -784,7 +842,11 @@ simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor, shnum = 0; for (section = sobj->sections; section != NULL; section = section->next) + { ++shnum; + if(section->relocations) + ++shnum; + } if (shnum > 0) { /* Add a section header for the dummy section, @@ -891,7 +953,7 @@ simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor, static int simple_object_elf_write_symbol(simple_object_write *sobj, int descriptor, - off_t offset, unsigned int st_name, unsigned int st_value, size_t st_size, + off_t offset, unsigned int st_name, unsigned long int st_value, size_t st_size, unsigned char st_info, unsigned char st_other, unsigned int st_shndx, const char **errmsg, int *err) { @@ -900,38 +962,57 @@ simple_object_elf_write_symbol(simple_object_write *sobj, int descriptor, const struct elf_type_functions* fns; unsigned char cl; size_t sym_size; - unsigned char buf[sizeof (Elf64_External_Shdr)]; + unsigned char buf[sizeof (Elf64_External_Sym)]; fns = attrs->type_functions; cl = attrs->ei_class; sym_size = (cl == ELFCLASS32 - ? sizeof (Elf32_External_Shdr) - : sizeof (Elf64_External_Shdr)); - memset (buf, 0, sizeof (Elf64_External_Shdr)); + ? sizeof (Elf32_External_Sym) + : sizeof (Elf64_External_Sym)); + memset (buf, 0, sizeof (Elf64_External_Sym)); + + ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name); + ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value); + ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size); + buf[4]=st_info; + buf[5]=st_other; + ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx); - if(cl==ELFCLASS32) - { - ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name); - ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value); - ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size); - buf[4]=st_info; - buf[5]=st_other; - ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx); - } - else - { - ELF_SET_FIELD(fns, cl, Sym, buf, st_name, Elf_Word, st_name); - buf[4]=st_info; - buf[5]=st_other; - ELF_SET_FIELD(fns, cl, Sym, buf, st_shndx, Elf_Half, st_shndx); - ELF_SET_FIELD(fns, cl, Sym, buf, st_value, Elf_Addr, st_value); - ELF_SET_FIELD(fns, cl, Sym, buf, st_size, Elf_Addr, st_size); - } return simple_object_internal_write(descriptor, offset,buf,sym_size, errmsg,err); } +/* Write out an ELF R_X86_64_32 relocation entry */ + +static int +simple_object_elf_write_relocation(simple_object_write *sobj, int descriptor, + off_t offset, unsigned long r_offset, unsigned long r_info, + long r_addend, const char **errmsg, int *err) +{ + struct simple_object_elf_attributes *attrs = + (struct simple_object_elf_attributes *) sobj->data; + const struct elf_type_functions* fns; + unsigned char cl; + size_t rel_size; + unsigned char buf[sizeof (Elf64_External_Rela)]; + + fns = attrs->type_functions; + cl = attrs->ei_class; + + rel_size = cl == ELFCLASS32? sizeof(Elf32_External_Rela): + sizeof(Elf64_External_Rela); + + memset (buf, 0, sizeof (Elf64_External_Rela)); + ELF_SET_FIELD(fns, cl, Rela, buf, r_offset, Elf_Addr, r_offset); + ELF_SET_FIELD(fns, cl, Rela, buf, r_info, Elf_Addr, r_info); + ELF_SET_FIELD(fns, cl, Rela, buf, r_addend, Elf_Addr, r_addend); + + return simple_object_internal_write(descriptor, offset, buf, rel_size, + errmsg,err); +} + + /* Write out a complete ELF file. Ehdr initial dummy Shdr @@ -978,15 +1059,19 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, shnum = 0; for (section = sobj->sections; section != NULL; section = section->next) + { ++shnum; + /* count the relocation section too if there exist any relocations */ + if(section->relocations) ++shnum; + } if (shnum == 0) return NULL; /* Add initial dummy Shdr and .shstrtab */ shnum += 2; /*add initial .symtab and .strtab if symbol exists */ - if(sobj->symbols) - shnum += 2; + if(sobj->symbols) + shnum += 2; shdr_offset = ehdr_size; sh_offset = shdr_offset + shnum * shdr_size; @@ -1008,6 +1093,15 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, sh_name = 1; secnum = 0; + unsigned int section_idx = 1; + unsigned int debug_info_idx=1; + /* Relocation symbol index will start from 1, 0 being dummy symbol */ + unsigned long sym_idx = 1; + /* An array to store the .symtab index of relocation symbol */ + unsigned long rel_symtab_idx[5]; + for(int i=0; i<5; i++) + rel_symtab_idx[i] = -1; + for (section = sobj->sections; section != NULL; section = section->next) { size_t mask; @@ -1087,7 +1181,69 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, shdr_offset += shdr_size; sh_name += strlen (section->name) + 1; sh_offset += sh_size; + if(!strcmp(section->name,".gnu.debuglto_.debug_info")) + debug_info_idx=section_idx; + ++section_idx; + /* If the section has relocation, write out the relocation section */ + if( section->relocations) + { + sh_size=0; + struct simple_object_write_section_relocation *relocation; + sh_entsize = cl == ELFCLASS32 ? sizeof(Elf32_External_Rela) : sizeof(Elf64_External_Rela); + + for(relocation = section->relocations; relocation != NULL; relocation = relocation->next) + { + + int idx=-1; + if(!strcmp(relocation->name,".gnu.debuglto_.debug_info")) + idx=DEBUG_INFO_IDX; + else if(!strcmp(relocation->name,".gnu.debuglto_.debug_abbrev")) + idx=DEBUG_ABBREV_IDX; + else if(!strcmp(relocation->name,".gnu.debuglto_.debug_str")) + idx=DEBUG_STR_IDX; + else if(!strcmp(relocation->name,".gnu.debuglto_.debug_line")) + idx=DEBUG_LINE_IDX; + else if(!strcmp(relocation->name,".gnu.debuglto_.debug_line_str")) + idx=DEBUG_LINE_STR_IDX; + if(idx < 0) + continue; + /* Add the relocation symbol to .symtab if it hasn't been already added */ + if(rel_symtab_idx[idx]==(unsigned long)-1) + { + simple_object_write_add_symbol(sobj,relocation->name, 0, 0, + STB_LOCAL, STT_SECTION, relocation->rel_sec_idx+debug_info_idx,0); + rel_symtab_idx[idx]=sym_idx; + sym_idx++; + } + /* write the relocation entry */ + unsigned long r_info = cl==ELFCLASS32 ? ELF32_R_INFO(rel_symtab_idx[idx], R_X86_64_32): + ELF64_R_INFO(rel_symtab_idx[idx], R_X86_64_32); + if(!simple_object_elf_write_relocation(sobj, descriptor, sh_offset+sh_size, + relocation->offset, r_info, relocation->addend, &errmsg, err)) + return errmsg; + sh_size+=sh_entsize; + + } + + sh_addralign = cl==ELFCLASS32 ? 0x04 : 0x08; + + if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, + sh_name, SHT_RELA, SHF_INFO_LINK, + 0, sh_offset, + sh_size, shnum-3, section_idx-1, + sh_addralign, sh_entsize, + &errmsg, err)) + return errmsg; + + + shdr_offset += shdr_size; + sh_name += (strlen(".rela")+strlen(section->name) + 1); + sh_offset += sh_size; + ++section_idx; + } + } + /*Write out the whole .symtab and .strtab*/ if(sobj->symbols) { @@ -1097,43 +1253,73 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, for(symbol=sobj->symbols; symbol!=NULL; symbol=symbol->next) { ++num_sym; - } + } - size_t sym_size = cl==ELFCLASS32?sizeof(Elf32_External_Sym):sizeof(Elf64_External_Sym); - size_t sh_addralign = cl==ELFCLASS32?0x04:0x08; - size_t sh_entsize = sym_size; - size_t sh_size = num_sym*sym_size; - unsigned int sh_info = 2; - if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, - sh_name, SHT_SYMTAB, 0, 0, sh_offset, - sh_size, shnum-2, sh_info, - sh_addralign,sh_entsize, &errmsg, err)) - return errmsg; - shdr_offset += shdr_size; - sh_name += strlen(".symtab")+1; - /*Writes out the dummy symbol */ + unsigned int st_name_size = 1; + unsigned int num_local_sym = 0; + size_t sh_entsize= cl==ELFCLASS32 ? sizeof(Elf32_External_Sym) : sizeof(Elf64_External_Sym); + size_t sh_addralign = cl==ELFCLASS32 ? 0x04 : 0x08; + size_t sh_size = 0; + /*Writes out the dummy symbol */ if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset, 0,0,0,0,0,SHN_UNDEF,&errmsg,err)) return errmsg; - sh_offset += sym_size; - unsigned int st_name=1; + sh_size += sh_entsize; + + /* First write all local symbols */ + for(symbol=sobj->symbols; symbol!=NULL; symbol=symbol->next) + { + if(symbol->bind!=STB_LOCAL) + continue; + ++num_local_sym; + unsigned int st_value = symbol->value; + unsigned int st_size = symbol->size; + unsigned short int st_shndx = symbol->shndx==(unsigned short int)-1 ? SHN_COMMON : symbol->shndx; + unsigned char st_info = ELF_ST_INFO(symbol->bind,symbol->type); + unsigned char st_other = symbol->st_other; + + if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset+sh_size, + st_name_size,st_value,st_size,st_info,st_other,st_shndx,&errmsg,err)) + return errmsg; + + sh_size += sh_entsize; + st_name_size += strlen(symbol->name)+1; + + } + /* Write out the global and other symbols */ for(symbol=sobj->symbols; symbol!=NULL; symbol=symbol->next) { - unsigned int st_value = 1; - unsigned int st_size = 1; - unsigned char st_info = 17; - if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset, - st_name,st_value,st_size,st_info,0,SHN_COMMON,&errmsg,err)) + if(symbol->bind==STB_LOCAL) + continue; + unsigned int st_value = symbol->value; + unsigned int st_size = symbol->size; + unsigned short int st_shndx = symbol->shndx==(unsigned short int)-1 ? SHN_COMMON : symbol->shndx; + unsigned char st_info = ELF_ST_INFO(symbol->bind,symbol->type); + unsigned char st_other = symbol->st_other; + + if(!simple_object_elf_write_symbol(sobj, descriptor, sh_offset+sh_size, + st_name_size,st_value,st_size,st_info,st_other,st_shndx,&errmsg,err)) return errmsg; - sh_offset += sym_size; - st_name += strlen(symbol->name)+1; + + sh_size += sh_entsize; + st_name_size += strlen(symbol->name)+1; } + unsigned int sh_info = num_local_sym+1; + if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, + sh_name, SHT_SYMTAB, 0, 0, sh_offset, + sh_size, shnum-2, sh_info, + sh_addralign,sh_entsize, &errmsg, err)) + return errmsg; + shdr_offset += shdr_size; + sh_offset+=sh_size; + sh_name += strlen(".symtab")+1; + if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset, sh_name, SHT_STRTAB, 0, 0, sh_offset, - st_name, 0, 0, + st_name_size, 0, 0, 1, 0, &errmsg, err)) return errmsg; shdr_offset += shdr_size; @@ -1144,10 +1330,25 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, &errmsg, err)) return errmsg; ++sh_offset; + /* write out the local symbols name */ + for(symbol = sobj->symbols; symbol!=NULL; symbol = symbol->next) + { + if(symbol->bind != STB_LOCAL) + continue; + size_t len = strlen(symbol->name)+1; + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) symbol->name, + len, &errmsg, err)) + return errmsg; + sh_offset += len; + } + /* write out the global and other symbols name */ for(symbol=sobj->symbols;symbol!=NULL;symbol=symbol->next) { - size_t len=strlen(symbol->name)+1; + if(symbol->bind == STB_LOCAL) + continue; + size_t len = strlen(symbol->name)+1; if (!simple_object_internal_write (descriptor, sh_offset, (const unsigned char *) symbol->name, len, &errmsg, err)) @@ -1179,6 +1380,22 @@ simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor, len, &errmsg, err)) return errmsg; sh_offset += len; + + if(section->relocations) + { + /* Adds the .rela prefix and write it to .shstrtab */ + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) ".rela",strlen(".rela"), &errmsg, err)) + return errmsg; + + sh_offset += strlen(".rela"); + len = strlen (section->name) + 1; + if (!simple_object_internal_write (descriptor, sh_offset, + (const unsigned char *) section->name, + len, &errmsg, err)) + return errmsg; + sh_offset += len; + } } /*Adds the name .symtab and .strtab*/ if(sobj->symbols) diff --git a/libiberty/simple-object.c b/libiberty/simple-object.c index 1f9141aedb4..dcdd129a869 100644 --- a/libiberty/simple-object.c +++ b/libiberty/simple-object.c @@ -476,6 +476,8 @@ simple_object_write_create_section (simple_object_write *sobj, const char *name, ret->align = align; ret->buffers = NULL; ret->last_buffer = NULL; + ret->relocations = NULL; + ret->last_relocation = NULL; if (sobj->last_section == NULL)