68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1 /* simple-object-elf.c -- routines to manipulate ELF object files.
|
145
|
2 Copyright (C) 2010-2020 Free Software Foundation, Inc.
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
3 Written by Ian Lance Taylor, Google.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
4
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
5 This program is free software; you can redistribute it and/or modify it
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
6 under the terms of the GNU General Public License as published by the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
7 Free Software Foundation; either version 2, or (at your option) any
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
8 later version.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
9
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
10 This program is distributed in the hope that it will be useful,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
13 GNU General Public License for more details.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
14
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
15 You should have received a copy of the GNU General Public License
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
16 along with this program; if not, write to the Free Software
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
17 Foundation, 51 Franklin Street - Fifth Floor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
18 Boston, MA 02110-1301, USA. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
19
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
20 #include "config.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
21 #include "libiberty.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
22 #include "simple-object.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
23
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
24 #include <errno.h>
|
131
|
25 /* mingw.org's MinGW doesn't have ENOTSUP. */
|
|
26 #ifndef ENOTSUP
|
|
27 # define ENOTSUP ENOSYS
|
|
28 #endif
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
29 #include <stddef.h>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
30
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
31 #ifdef HAVE_STDLIB_H
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
32 #include <stdlib.h>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
33 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
34
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
35 #ifdef HAVE_STDINT_H
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
36 #include <stdint.h>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
37 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
38
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
39 #ifdef HAVE_STRING_H
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
40 #include <string.h>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
41 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
42
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
43 #ifdef HAVE_INTTYPES_H
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
44 #include <inttypes.h>
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
45 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
46
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
47 #include "simple-object-common.h"
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
48
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
49 /* ELF structures and constants. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
50
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
51 /* 32-bit ELF file header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
52
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
53 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
54 unsigned char e_ident[16]; /* ELF "magic number" */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
55 unsigned char e_type[2]; /* Identifies object file type */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
56 unsigned char e_machine[2]; /* Specifies required architecture */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
57 unsigned char e_version[4]; /* Identifies object file version */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
58 unsigned char e_entry[4]; /* Entry point virtual address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
59 unsigned char e_phoff[4]; /* Program header table file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
60 unsigned char e_shoff[4]; /* Section header table file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
61 unsigned char e_flags[4]; /* Processor-specific flags */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
62 unsigned char e_ehsize[2]; /* ELF header size in bytes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
63 unsigned char e_phentsize[2]; /* Program header table entry size */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
64 unsigned char e_phnum[2]; /* Program header table entry count */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
65 unsigned char e_shentsize[2]; /* Section header table entry size */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
66 unsigned char e_shnum[2]; /* Section header table entry count */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
67 unsigned char e_shstrndx[2]; /* Section header string table index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
68 } Elf32_External_Ehdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
69
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
70 /* 64-bit ELF file header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
71
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
72 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
73 unsigned char e_ident[16]; /* ELF "magic number" */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
74 unsigned char e_type[2]; /* Identifies object file type */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
75 unsigned char e_machine[2]; /* Specifies required architecture */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
76 unsigned char e_version[4]; /* Identifies object file version */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
77 unsigned char e_entry[8]; /* Entry point virtual address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
78 unsigned char e_phoff[8]; /* Program header table file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
79 unsigned char e_shoff[8]; /* Section header table file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
80 unsigned char e_flags[4]; /* Processor-specific flags */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
81 unsigned char e_ehsize[2]; /* ELF header size in bytes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
82 unsigned char e_phentsize[2]; /* Program header table entry size */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
83 unsigned char e_phnum[2]; /* Program header table entry count */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
84 unsigned char e_shentsize[2]; /* Section header table entry size */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
85 unsigned char e_shnum[2]; /* Section header table entry count */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
86 unsigned char e_shstrndx[2]; /* Section header string table index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
87 } Elf64_External_Ehdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
88
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
89 /* Indexes and values in e_ident field of Ehdr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
90
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
91 #define EI_MAG0 0 /* File identification byte 0 index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
92 #define ELFMAG0 0x7F /* Magic number byte 0 */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
93
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
94 #define EI_MAG1 1 /* File identification byte 1 index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
95 #define ELFMAG1 'E' /* Magic number byte 1 */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
96
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
97 #define EI_MAG2 2 /* File identification byte 2 index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
98 #define ELFMAG2 'L' /* Magic number byte 2 */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
99
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
100 #define EI_MAG3 3 /* File identification byte 3 index */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
101 #define ELFMAG3 'F' /* Magic number byte 3 */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
102
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
103 #define EI_CLASS 4 /* File class */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
104 #define ELFCLASSNONE 0 /* Invalid class */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
105 #define ELFCLASS32 1 /* 32-bit objects */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
106 #define ELFCLASS64 2 /* 64-bit objects */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
107
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
108 #define EI_DATA 5 /* Data encoding */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
109 #define ELFDATANONE 0 /* Invalid data encoding */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
110 #define ELFDATA2LSB 1 /* 2's complement, little endian */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
111 #define ELFDATA2MSB 2 /* 2's complement, big endian */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
112
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
113 #define EI_VERSION 6 /* File version */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
114 #define EV_CURRENT 1 /* Current version */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
115
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
116 #define EI_OSABI 7 /* Operating System/ABI indication */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
117
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
118 /* Values for e_type field of Ehdr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
119
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
120 #define ET_REL 1 /* Relocatable file */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
121
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
122 /* Values for e_machine field of Ehdr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
123
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
124 #define EM_SPARC 2 /* SUN SPARC */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
125 #define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
126
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
127 /* Special section index values. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
128
|
111
|
129 #define SHN_UNDEF 0 /* Undefined section */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
130 #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
|
111
|
131 #define SHN_COMMON 0xFFF2 /* Associated symbol is in common */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
132 #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
|
131
|
133 #define SHN_HIRESERVE 0xffff /* End of reserved indices */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
134
|
111
|
135
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
136 /* 32-bit ELF program header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
137
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
138 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
139 unsigned char p_type[4]; /* Identifies program segment type */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
140 unsigned char p_offset[4]; /* Segment file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
141 unsigned char p_vaddr[4]; /* Segment virtual address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
142 unsigned char p_paddr[4]; /* Segment physical address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
143 unsigned char p_filesz[4]; /* Segment size in file */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
144 unsigned char p_memsz[4]; /* Segment size in memory */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
145 unsigned char p_flags[4]; /* Segment flags */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
146 unsigned char p_align[4]; /* Segment alignment, file & memory */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
147 } Elf32_External_Phdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
148
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
149 /* 64-bit ELF program header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
150
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
151 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
152 unsigned char p_type[4]; /* Identifies program segment type */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
153 unsigned char p_flags[4]; /* Segment flags */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
154 unsigned char p_offset[8]; /* Segment file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
155 unsigned char p_vaddr[8]; /* Segment virtual address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
156 unsigned char p_paddr[8]; /* Segment physical address */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
157 unsigned char p_filesz[8]; /* Segment size in file */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
158 unsigned char p_memsz[8]; /* Segment size in memory */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
159 unsigned char p_align[8]; /* Segment alignment, file & memory */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
160 } Elf64_External_Phdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
161
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
162 /* 32-bit ELF section header */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
163
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
164 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
165 unsigned char sh_name[4]; /* Section name, index in string tbl */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
166 unsigned char sh_type[4]; /* Type of section */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
167 unsigned char sh_flags[4]; /* Miscellaneous section attributes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
168 unsigned char sh_addr[4]; /* Section virtual addr at execution */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
169 unsigned char sh_offset[4]; /* Section file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
170 unsigned char sh_size[4]; /* Size of section in bytes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
171 unsigned char sh_link[4]; /* Index of another section */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
172 unsigned char sh_info[4]; /* Additional section information */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
173 unsigned char sh_addralign[4]; /* Section alignment */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
174 unsigned char sh_entsize[4]; /* Entry size if section holds table */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
175 } Elf32_External_Shdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
176
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
177 /* 64-bit ELF section header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
178
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
179 typedef struct {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
180 unsigned char sh_name[4]; /* Section name, index in string tbl */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
181 unsigned char sh_type[4]; /* Type of section */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
182 unsigned char sh_flags[8]; /* Miscellaneous section attributes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
183 unsigned char sh_addr[8]; /* Section virtual addr at execution */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
184 unsigned char sh_offset[8]; /* Section file offset */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
185 unsigned char sh_size[8]; /* Size of section in bytes */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
186 unsigned char sh_link[4]; /* Index of another section */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
187 unsigned char sh_info[4]; /* Additional section information */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
188 unsigned char sh_addralign[8]; /* Section alignment */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
189 unsigned char sh_entsize[8]; /* Entry size if section holds table */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
190 } Elf64_External_Shdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
191
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
192 /* Values for sh_type field. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
193
|
111
|
194 #define SHT_NULL 0 /* Section header table entry unused */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
195 #define SHT_PROGBITS 1 /* Program data */
|
111
|
196 #define SHT_SYMTAB 2 /* Link editing symbol table */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
197 #define SHT_STRTAB 3 /* A string table */
|
111
|
198 #define SHT_RELA 4 /* Relocation entries with addends */
|
|
199 #define SHT_REL 9 /* Relocation entries, no addends */
|
|
200 #define SHT_GROUP 17 /* Section contains a section group */
|
131
|
201 #define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
|
111
|
202
|
|
203 /* Values for sh_flags field. */
|
|
204
|
131
|
205 #define SHF_INFO_LINK 0x00000040 /* `sh_info' contains SHT index */
|
111
|
206 #define SHF_EXECINSTR 0x00000004 /* Executable section. */
|
|
207 #define SHF_EXCLUDE 0x80000000 /* Link editor is to exclude this
|
|
208 section from executable and
|
|
209 shared library that it builds
|
|
210 when those objects are not to be
|
|
211 further relocated. */
|
|
212 /* Symbol table entry. */
|
|
213
|
|
214 typedef struct
|
|
215 {
|
|
216 unsigned char st_name[4]; /* Symbol name (string tbl index) */
|
|
217 unsigned char st_value[4]; /* Symbol value */
|
|
218 unsigned char st_size[4]; /* Symbol size */
|
|
219 unsigned char st_info; /* Symbol type and binding */
|
|
220 unsigned char st_other; /* Symbol visibility */
|
|
221 unsigned char st_shndx[2]; /* Section index */
|
|
222 } Elf32_External_Sym;
|
|
223
|
|
224 typedef struct
|
|
225 {
|
|
226 unsigned char st_name[4]; /* Symbol name (string tbl index) */
|
|
227 unsigned char st_info; /* Symbol type and binding */
|
|
228 unsigned char st_other; /* Symbol visibility */
|
|
229 unsigned char st_shndx[2]; /* Section index */
|
|
230 unsigned char st_value[8]; /* Symbol value */
|
|
231 unsigned char st_size[8]; /* Symbol size */
|
|
232 } Elf64_External_Sym;
|
|
233
|
|
234 #define ELF_ST_BIND(val) (((unsigned char) (val)) >> 4)
|
|
235 #define ELF_ST_TYPE(val) ((val) & 0xf)
|
|
236 #define ELF_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf))
|
|
237
|
|
238 #define STT_NOTYPE 0 /* Symbol type is unspecified */
|
|
239 #define STT_OBJECT 1 /* Symbol is a data object */
|
|
240 #define STT_FUNC 2 /* Symbol is a code object */
|
|
241 #define STT_TLS 6 /* Thread local data object */
|
|
242 #define STT_GNU_IFUNC 10 /* Symbol is an indirect code object */
|
|
243
|
|
244 #define STB_LOCAL 0 /* Local symbol */
|
|
245 #define STB_GLOBAL 1 /* Global symbol */
|
|
246 #define STB_WEAK 2 /* Weak global */
|
|
247
|
|
248 #define STV_DEFAULT 0 /* Visibility is specified by binding type */
|
|
249 #define STV_HIDDEN 2 /* Can only be seen inside currect component */
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
250
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
251 /* Functions to fetch and store different ELF types, depending on the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
252 endianness and size. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
253
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
254 struct elf_type_functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
255 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
256 unsigned short (*fetch_Elf_Half) (const unsigned char *);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
257 unsigned int (*fetch_Elf_Word) (const unsigned char *);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
258 ulong_type (*fetch_Elf_Addr) (const unsigned char *);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
259 void (*set_Elf_Half) (unsigned char *, unsigned short);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
260 void (*set_Elf_Word) (unsigned char *, unsigned int);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
261 void (*set_Elf_Addr) (unsigned char *, ulong_type);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
262 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
263
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
264 static const struct elf_type_functions elf_big_32_functions =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
265 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
266 simple_object_fetch_big_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
267 simple_object_fetch_big_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
268 simple_object_fetch_big_32_ulong,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
269 simple_object_set_big_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
270 simple_object_set_big_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
271 simple_object_set_big_32_ulong
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
272 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
273
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
274 static const struct elf_type_functions elf_little_32_functions =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
275 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
276 simple_object_fetch_little_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
277 simple_object_fetch_little_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
278 simple_object_fetch_little_32_ulong,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
279 simple_object_set_little_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
280 simple_object_set_little_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
281 simple_object_set_little_32_ulong
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
282 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
283
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
284 #ifdef UNSIGNED_64BIT_TYPE
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
285
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
286 static const struct elf_type_functions elf_big_64_functions =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
287 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
288 simple_object_fetch_big_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
289 simple_object_fetch_big_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
290 simple_object_fetch_big_64,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
291 simple_object_set_big_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
292 simple_object_set_big_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
293 simple_object_set_big_64
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
294 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
295
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
296 static const struct elf_type_functions elf_little_64_functions =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
297 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
298 simple_object_fetch_little_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
299 simple_object_fetch_little_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
300 simple_object_fetch_little_64,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
301 simple_object_set_little_16,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
302 simple_object_set_little_32,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
303 simple_object_set_little_64
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
304 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
305
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
306 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
307
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
308 /* Hideous macro to fetch the value of a field from an external ELF
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
309 struct of some sort. TYPEFUNCS is the set of type functions.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
310 BUFFER points to the external data. STRUCTTYPE is the appropriate
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
311 struct type. FIELD is a field within the struct. TYPE is the type
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
312 of the field in the struct: Elf_Half, Elf_Word, or Elf_Addr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
313
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
314 #define ELF_FETCH_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
315 ((TYPEFUNCS)->fetch_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD)))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
316
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
317 /* Even more hideous macro to fetch the value of FIELD from BUFFER.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
318 SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
319 elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
320 the struct. TYPE is the type of the field in the struct: Elf_Half,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
321 Elf_Word, or Elf_Addr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
322
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
323 #define ELF_FETCH_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
324 FIELD, TYPE) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
325 ELF_FETCH_STRUCT_FIELD (TYPEFUNCS, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
326 Elf ## SIZE ## _External_ ## STRUCTTYPE, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
327 FIELD, BUFFER, TYPE)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
328
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
329 /* Like ELF_FETCH_SIZED_FIELD but taking an ELFCLASS value. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
330
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
331 #define ELF_FETCH_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
332 FIELD, TYPE) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
333 ((CLASS) == ELFCLASS32 \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
334 ? ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
335 TYPE) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
336 : ELF_FETCH_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
337 TYPE))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
338
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
339 /* Hideous macro to set the value of a field in an external ELF
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
340 structure to VAL. TYPEFUNCS is the set of type functions. BUFFER
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
341 points to the external data. STRUCTTYPE is the appropriate
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
342 structure type. FIELD is a field within the struct. TYPE is the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
343 type of the field in the struct: Elf_Half, Elf_Word, or
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
344 Elf_Addr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
345
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
346 #define ELF_SET_STRUCT_FIELD(TYPEFUNCS, STRUCTTYPE, FIELD, BUFFER, TYPE, VAL) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
347 (TYPEFUNCS)->set_ ## TYPE ((BUFFER) + offsetof (STRUCTTYPE, FIELD), (VAL))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
348
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
349 /* Even more hideous macro to set the value of FIELD in BUFFER to VAL.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
350 SIZE is 32 or 64. STRUCTTYPE is the name of the struct from
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
351 elf/external.h: Ehdr, Shdr, etc. FIELD is the name of a field in
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
352 the struct. TYPE is the type of the field in the struct: Elf_Half,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
353 Elf_Word, or Elf_Addr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
354
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
355 #define ELF_SET_SIZED_FIELD(TYPEFUNCS, SIZE, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
356 TYPE, VAL) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
357 ELF_SET_STRUCT_FIELD (TYPEFUNCS, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
358 Elf ## SIZE ## _External_ ## STRUCTTYPE, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
359 FIELD, BUFFER, TYPE, VAL)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
360
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
361 /* Like ELF_SET_SIZED_FIELD but taking an ELFCLASS value. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
362
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
363 #define ELF_SET_FIELD(TYPEFUNCS, CLASS, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
364 TYPE, VAL) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
365 ((CLASS) == ELFCLASS32 \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
366 ? ELF_SET_SIZED_FIELD (TYPEFUNCS, 32, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
367 TYPE, VAL) \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
368 : ELF_SET_SIZED_FIELD (TYPEFUNCS, 64, STRUCTTYPE, BUFFER, FIELD, \
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
369 TYPE, VAL))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
370
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
371 /* Private data for an simple_object_read. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
372
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
373 struct simple_object_elf_read
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
374 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
375 /* Type functions. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
376 const struct elf_type_functions* type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
377 /* Elf data. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
378 unsigned char ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
379 /* Elf class. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
380 unsigned char ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
381 /* ELF OS ABI. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
382 unsigned char ei_osabi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
383 /* Elf machine number. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
384 unsigned short machine;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
385 /* Processor specific flags. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
386 unsigned int flags;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
387 /* File offset of section headers. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
388 ulong_type shoff;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
389 /* Number of sections. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
390 unsigned int shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
391 /* Index of string table section header. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
392 unsigned int shstrndx;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
393 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
394
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
395 /* Private data for an simple_object_attributes. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
396
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
397 struct simple_object_elf_attributes
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
398 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
399 /* Type functions. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
400 const struct elf_type_functions* type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
401 /* Elf data. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
402 unsigned char ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
403 /* Elf class. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
404 unsigned char ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
405 /* ELF OS ABI. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
406 unsigned char ei_osabi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
407 /* Elf machine number. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
408 unsigned short machine;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
409 /* Processor specific flags. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
410 unsigned int flags;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
411 };
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
412
|
111
|
413 /* Private data for an simple_object_write. */
|
|
414
|
|
415 struct simple_object_elf_write
|
|
416 {
|
|
417 struct simple_object_elf_attributes attrs;
|
|
418 unsigned char *shdrs;
|
|
419 };
|
|
420
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
421 /* See if we have an ELF file. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
422
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
423 static void *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
424 simple_object_elf_match (unsigned char header[SIMPLE_OBJECT_MATCH_HEADER_LEN],
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
425 int descriptor, off_t offset,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
426 const char *segment_name ATTRIBUTE_UNUSED,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
427 const char **errmsg, int *err)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
428 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
429 unsigned char ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
430 unsigned char ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
431 const struct elf_type_functions *type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
432 unsigned char ehdr[sizeof (Elf64_External_Ehdr)];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
433 struct simple_object_elf_read *eor;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
434
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
435 if (header[EI_MAG0] != ELFMAG0
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
436 || header[EI_MAG1] != ELFMAG1
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
437 || header[EI_MAG2] != ELFMAG2
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
438 || header[EI_MAG3] != ELFMAG3
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
439 || header[EI_VERSION] != EV_CURRENT)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
440 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
441 *errmsg = NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
442 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
443 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
444 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
445
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
446 ei_data = header[EI_DATA];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
447 if (ei_data != ELFDATA2LSB && ei_data != ELFDATA2MSB)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
448 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
449 *errmsg = "unknown ELF endianness";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
450 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
451 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
452 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
453
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
454 ei_class = header[EI_CLASS];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
455 switch (ei_class)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
456 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
457 case ELFCLASS32:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
458 type_functions = (ei_data == ELFDATA2LSB
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
459 ? &elf_little_32_functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
460 : &elf_big_32_functions);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
461 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
462
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
463 case ELFCLASS64:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
464 #ifndef UNSIGNED_64BIT_TYPE
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
465 *errmsg = "64-bit ELF objects not supported";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
466 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
467 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
468 #else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
469 type_functions = (ei_data == ELFDATA2LSB
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
470 ? &elf_little_64_functions
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
471 : &elf_big_64_functions);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
472 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
473 #endif
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
474
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
475 default:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
476 *errmsg = "unrecognized ELF size";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
477 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
478 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
479 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
480
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
481 if (!simple_object_internal_read (descriptor, offset, ehdr, sizeof ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
482 errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
483 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
484
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
485 eor = XNEW (struct simple_object_elf_read);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
486 eor->type_functions = type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
487 eor->ei_data = ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
488 eor->ei_class = ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
489 eor->ei_osabi = header[EI_OSABI];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
490 eor->machine = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
491 e_machine, Elf_Half);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
492 eor->flags = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
493 e_flags, Elf_Word);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
494 eor->shoff = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
495 e_shoff, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
496 eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
497 e_shnum, Elf_Half);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
498 eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Ehdr, ehdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
499 e_shstrndx, Elf_Half);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
500
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
501 if ((eor->shnum == 0 || eor->shstrndx == SHN_XINDEX)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
502 && eor->shoff != 0)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
503 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
504 unsigned char shdr[sizeof (Elf64_External_Shdr)];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
505
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
506 /* Object file has more than 0xffff sections. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
507
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
508 if (!simple_object_internal_read (descriptor, offset + eor->shoff, shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
509 (ei_class == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
510 ? sizeof (Elf32_External_Shdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
511 : sizeof (Elf64_External_Shdr)),
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
512 errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
513 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
514 XDELETE (eor);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
515 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
516 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
517
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
518 if (eor->shnum == 0)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
519 eor->shnum = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
520 shdr, sh_size, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
521
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
522 if (eor->shstrndx == SHN_XINDEX)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
523 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
524 eor->shstrndx = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
525 shdr, sh_link, Elf_Word);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
526
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
527 /* Versions of the GNU binutils between 2.12 and 2.18 did
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
528 not handle objects with more than SHN_LORESERVE sections
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
529 correctly. All large section indexes were offset by
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
530 0x100. There is more information at
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
531 http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
532 Fortunately these object files are easy to detect, as the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
533 GNU binutils always put the section header string table
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
534 near the end of the list of sections. Thus if the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
535 section header string table index is larger than the
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
536 number of sections, then we know we have to subtract
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
537 0x100 to get the real section index. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
538 if (eor->shstrndx >= eor->shnum
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
539 && eor->shstrndx >= SHN_LORESERVE + 0x100)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
540 eor->shstrndx -= 0x100;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
541 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
542 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
543
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
544 if (eor->shstrndx >= eor->shnum)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
545 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
546 *errmsg = "invalid ELF shstrndx >= shnum";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
547 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
548 XDELETE (eor);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
549 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
550 }
|
145
|
551
|
|
552 if (eor->shstrndx == 0)
|
|
553 {
|
|
554 *errmsg = "invalid ELF shstrndx == 0";
|
|
555 *err = 0;
|
|
556 XDELETE (eor);
|
|
557 return NULL;
|
|
558 }
|
|
559
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
560 return (void *) eor;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
561 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
562
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
563 /* Find all sections in an ELF file. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
564
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
565 static const char *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
566 simple_object_elf_find_sections (simple_object_read *sobj,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
567 int (*pfn) (void *, const char *,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
568 off_t offset, off_t length),
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
569 void *data,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
570 int *err)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
571 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
572 struct simple_object_elf_read *eor =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
573 (struct simple_object_elf_read *) sobj->data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
574 const struct elf_type_functions *type_functions = eor->type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
575 unsigned char ei_class = eor->ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
576 size_t shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
577 unsigned int shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
578 unsigned char *shdrs;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
579 const char *errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
580 unsigned char *shstrhdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
581 size_t name_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
582 off_t shstroff;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
583 unsigned char *names;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
584 unsigned int i;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
585
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
586 shdr_size = (ei_class == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
587 ? sizeof (Elf32_External_Shdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
588 : sizeof (Elf64_External_Shdr));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
589
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
590 /* Read the section headers. We skip section 0, which is not a
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
591 useful section. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
592
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
593 shnum = eor->shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
594 shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
595
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
596 if (!simple_object_internal_read (sobj->descriptor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
597 sobj->offset + eor->shoff + shdr_size,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
598 shdrs,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
599 shdr_size * (shnum - 1),
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
600 &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
601 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
602 XDELETEVEC (shdrs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
603 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
604 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
605
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
606 /* Read the section names. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
607
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
608 shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
609 name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
610 shstrhdr, sh_size, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
611 shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
612 shstrhdr, sh_offset, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
613 names = XNEWVEC (unsigned char, name_size);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
614 if (!simple_object_internal_read (sobj->descriptor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
615 sobj->offset + shstroff,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
616 names, name_size, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
617 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
618 XDELETEVEC (names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
619 XDELETEVEC (shdrs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
620 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
621 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
622
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
623 for (i = 1; i < shnum; ++i)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
624 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
625 unsigned char *shdr;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
626 unsigned int sh_name;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
627 const char *name;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
628 off_t offset;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
629 off_t length;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
630
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
631 shdr = shdrs + (i - 1) * shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
632 sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
633 shdr, sh_name, Elf_Word);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
634 if (sh_name >= name_size)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
635 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
636 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
637 XDELETEVEC (names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
638 XDELETEVEC (shdrs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
639 return "ELF section name out of range";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
640 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
641
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
642 name = (const char *) names + sh_name;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
643 offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
644 shdr, sh_offset, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
645 length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
646 shdr, sh_size, Elf_Addr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
647
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
648 if (!(*pfn) (data, name, offset, length))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
649 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
650 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
651
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
652 XDELETEVEC (names);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
653 XDELETEVEC (shdrs);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
654
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
655 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
656 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
657
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
658 /* Fetch the attributes for an simple_object_read. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
659
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
660 static void *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
661 simple_object_elf_fetch_attributes (simple_object_read *sobj,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
662 const char **errmsg ATTRIBUTE_UNUSED,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
663 int *err ATTRIBUTE_UNUSED)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
664 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
665 struct simple_object_elf_read *eor =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
666 (struct simple_object_elf_read *) sobj->data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
667 struct simple_object_elf_attributes *ret;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
668
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
669 ret = XNEW (struct simple_object_elf_attributes);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
670 ret->type_functions = eor->type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
671 ret->ei_data = eor->ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
672 ret->ei_class = eor->ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
673 ret->ei_osabi = eor->ei_osabi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
674 ret->machine = eor->machine;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
675 ret->flags = eor->flags;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
676 return ret;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
677 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
678
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
679 /* Release the privata data for an simple_object_read. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
680
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
681 static void
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
682 simple_object_elf_release_read (void *data)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
683 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
684 XDELETE (data);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
685 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
686
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
687 /* Compare two attributes structures. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
688
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
689 static const char *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
690 simple_object_elf_attributes_merge (void *todata, void *fromdata, int *err)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
691 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
692 struct simple_object_elf_attributes *to =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
693 (struct simple_object_elf_attributes *) todata;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
694 struct simple_object_elf_attributes *from =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
695 (struct simple_object_elf_attributes *) fromdata;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
696
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
697 if (to->ei_data != from->ei_data || to->ei_class != from->ei_class)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
698 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
699 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
700 return "ELF object format mismatch";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
701 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
702
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
703 if (to->machine != from->machine)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
704 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
705 int ok;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
706
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
707 /* EM_SPARC and EM_SPARC32PLUS are compatible and force an
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
708 output of EM_SPARC32PLUS. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
709 ok = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
710 switch (to->machine)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
711 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
712 case EM_SPARC:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
713 if (from->machine == EM_SPARC32PLUS)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
714 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
715 to->machine = from->machine;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
716 ok = 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
717 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
718 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
719
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
720 case EM_SPARC32PLUS:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
721 if (from->machine == EM_SPARC)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
722 ok = 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
723 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
724
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
725 default:
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
726 break;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
727 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
728
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
729 if (!ok)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
730 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
731 *err = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
732 return "ELF machine number mismatch";
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
733 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
734 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
735
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
736 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
737 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
738
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
739 /* Release the private data for an attributes structure. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
740
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
741 static void
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
742 simple_object_elf_release_attributes (void *data)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
743 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
744 XDELETE (data);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
745 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
746
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
747 /* Prepare to write out a file. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
748
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
749 static void *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
750 simple_object_elf_start_write (void *attributes_data,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
751 const char **errmsg ATTRIBUTE_UNUSED,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
752 int *err ATTRIBUTE_UNUSED)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
753 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
754 struct simple_object_elf_attributes *attrs =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
755 (struct simple_object_elf_attributes *) attributes_data;
|
111
|
756 struct simple_object_elf_write *ret;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
757
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
758 /* We're just going to record the attributes, but we need to make a
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
759 copy because the user may delete them. */
|
111
|
760 ret = XNEW (struct simple_object_elf_write);
|
|
761 ret->attrs = *attrs;
|
|
762 ret->shdrs = NULL;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
763 return ret;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
764 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
765
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
766 /* Write out an ELF ehdr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
767
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
768 static int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
769 simple_object_elf_write_ehdr (simple_object_write *sobj, int descriptor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
770 const char **errmsg, int *err)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
771 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
772 struct simple_object_elf_attributes *attrs =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
773 (struct simple_object_elf_attributes *) sobj->data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
774 const struct elf_type_functions* fns;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
775 unsigned char cl;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
776 size_t ehdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
777 unsigned char buf[sizeof (Elf64_External_Ehdr)];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
778 simple_object_write_section *section;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
779 unsigned int shnum;
|
111
|
780 unsigned int shstrndx;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
781
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
782 fns = attrs->type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
783 cl = attrs->ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
784
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
785 shnum = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
786 for (section = sobj->sections; section != NULL; section = section->next)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
787 ++shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
788 if (shnum > 0)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
789 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
790 /* Add a section header for the dummy section and one for
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
791 .shstrtab. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
792 shnum += 2;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
793 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
794
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
795 ehdr_size = (cl == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
796 ? sizeof (Elf32_External_Ehdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
797 : sizeof (Elf64_External_Ehdr));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
798 memset (buf, 0, sizeof (Elf64_External_Ehdr));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
799
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
800 buf[EI_MAG0] = ELFMAG0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
801 buf[EI_MAG1] = ELFMAG1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
802 buf[EI_MAG2] = ELFMAG2;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
803 buf[EI_MAG3] = ELFMAG3;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
804 buf[EI_CLASS] = cl;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
805 buf[EI_DATA] = attrs->ei_data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
806 buf[EI_VERSION] = EV_CURRENT;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
807 buf[EI_OSABI] = attrs->ei_osabi;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
808
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
809 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_type, Elf_Half, ET_REL);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
810 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_machine, Elf_Half, attrs->machine);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
811 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_version, Elf_Word, EV_CURRENT);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
812 /* e_entry left as zero. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
813 /* e_phoff left as zero. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
814 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shoff, Elf_Addr, ehdr_size);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
815 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_flags, Elf_Word, attrs->flags);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
816 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_ehsize, Elf_Half, ehdr_size);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
817 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_phentsize, Elf_Half,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
818 (cl == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
819 ? sizeof (Elf32_External_Phdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
820 : sizeof (Elf64_External_Phdr)));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
821 /* e_phnum left as zero. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
822 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shentsize, Elf_Half,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
823 (cl == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
824 ? sizeof (Elf32_External_Shdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
825 : sizeof (Elf64_External_Shdr)));
|
111
|
826 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shnum, Elf_Half,
|
|
827 shnum >= SHN_LORESERVE ? 0 : shnum);
|
|
828 if (shnum == 0)
|
|
829 shstrndx = 0;
|
|
830 else
|
|
831 {
|
|
832 shstrndx = shnum - 1;
|
|
833 if (shstrndx >= SHN_LORESERVE)
|
|
834 shstrndx = SHN_XINDEX;
|
|
835 }
|
|
836 ELF_SET_FIELD (fns, cl, Ehdr, buf, e_shstrndx, Elf_Half, shstrndx);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
837
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
838 return simple_object_internal_write (descriptor, 0, buf, ehdr_size,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
839 errmsg, err);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
840 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
841
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
842 /* Write out an ELF shdr. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
843
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
844 static int
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
845 simple_object_elf_write_shdr (simple_object_write *sobj, int descriptor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
846 off_t offset, unsigned int sh_name,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
847 unsigned int sh_type, unsigned int sh_flags,
|
111
|
848 off_t sh_addr,
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
849 unsigned int sh_offset, unsigned int sh_size,
|
111
|
850 unsigned int sh_link, unsigned int sh_info,
|
|
851 size_t sh_addralign,
|
|
852 size_t sh_entsize,
|
|
853 const char **errmsg, int *err)
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
854 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
855 struct simple_object_elf_attributes *attrs =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
856 (struct simple_object_elf_attributes *) sobj->data;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
857 const struct elf_type_functions* fns;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
858 unsigned char cl;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
859 size_t shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
860 unsigned char buf[sizeof (Elf64_External_Shdr)];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
861
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
862 fns = attrs->type_functions;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
863 cl = attrs->ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
864
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
865 shdr_size = (cl == ELFCLASS32
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
866 ? sizeof (Elf32_External_Shdr)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
867 : sizeof (Elf64_External_Shdr));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
868 memset (buf, 0, sizeof (Elf64_External_Shdr));
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
869
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
870 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_name, Elf_Word, sh_name);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
871 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_type, Elf_Word, sh_type);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
872 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_flags, Elf_Addr, sh_flags);
|
111
|
873 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addr, Elf_Addr, sh_addr);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
874 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_offset, Elf_Addr, sh_offset);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
875 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_size, Elf_Addr, sh_size);
|
111
|
876 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_link, Elf_Word, sh_link);
|
|
877 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_info, Elf_Word, sh_info);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
878 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_addralign, Elf_Addr, sh_addralign);
|
111
|
879 ELF_SET_FIELD (fns, cl, Shdr, buf, sh_entsize, Elf_Addr, sh_entsize);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
880
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
881 return simple_object_internal_write (descriptor, offset, buf, shdr_size,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
882 errmsg, err);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
883 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
884
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
885 /* Write out a complete ELF file.
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
886 Ehdr
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
887 initial dummy Shdr
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
888 user-created Shdrs
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
889 .shstrtab Shdr
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
890 user-created section data
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
891 .shstrtab data */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
892
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
893 static const char *
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
894 simple_object_elf_write_to_file (simple_object_write *sobj, int descriptor,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
895 int *err)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
896 {
|
111
|
897 struct simple_object_elf_write *eow =
|
|
898 (struct simple_object_elf_write *) sobj->data;
|
|
899 struct simple_object_elf_attributes *attrs = &eow->attrs;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
900 unsigned char cl;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
901 size_t ehdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
902 size_t shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
903 const char *errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
904 simple_object_write_section *section;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
905 unsigned int shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
906 size_t shdr_offset;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
907 size_t sh_offset;
|
111
|
908 unsigned int first_sh_size;
|
|
909 unsigned int first_sh_link;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
910 size_t sh_name;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
911 unsigned char zero;
|
111
|
912 unsigned secnum;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
913
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
914 if (!simple_object_elf_write_ehdr (sobj, descriptor, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
915 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
916
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
917 cl = attrs->ei_class;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
918 if (cl == ELFCLASS32)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
919 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
920 ehdr_size = sizeof (Elf32_External_Ehdr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
921 shdr_size = sizeof (Elf32_External_Shdr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
922 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
923 else
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
924 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
925 ehdr_size = sizeof (Elf64_External_Ehdr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
926 shdr_size = sizeof (Elf64_External_Shdr);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
927 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
928
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
929 shnum = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
930 for (section = sobj->sections; section != NULL; section = section->next)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
931 ++shnum;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
932 if (shnum == 0)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
933 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
934
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
935 /* Add initial dummy Shdr and .shstrtab. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
936 shnum += 2;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
937
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
938 shdr_offset = ehdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
939 sh_offset = shdr_offset + shnum * shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
940
|
111
|
941 if (shnum < SHN_LORESERVE)
|
|
942 first_sh_size = 0;
|
|
943 else
|
|
944 first_sh_size = shnum;
|
|
945 if (shnum - 1 < SHN_LORESERVE)
|
|
946 first_sh_link = 0;
|
|
947 else
|
|
948 first_sh_link = shnum - 1;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
949 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
111
|
950 0, 0, 0, 0, 0, first_sh_size, first_sh_link,
|
|
951 0, 0, 0, &errmsg, err))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
952 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
953
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
954 shdr_offset += shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
955
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
956 sh_name = 1;
|
111
|
957 secnum = 0;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
958 for (section = sobj->sections; section != NULL; section = section->next)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
959 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
960 size_t mask;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
961 size_t new_sh_offset;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
962 size_t sh_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
963 struct simple_object_write_section_buffer *buffer;
|
111
|
964 unsigned int sh_type = SHT_PROGBITS;
|
|
965 unsigned int sh_flags = 0;
|
|
966 off_t sh_addr = 0;
|
|
967 unsigned int sh_link = 0;
|
|
968 unsigned int sh_info = 0;
|
|
969 size_t sh_addralign = 1U << section->align;
|
|
970 size_t sh_entsize = 0;
|
|
971 if (eow->shdrs)
|
|
972 {
|
|
973 sh_type = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
974 eow->shdrs + secnum * shdr_size,
|
|
975 sh_type, Elf_Word);
|
|
976 sh_flags = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
977 eow->shdrs + secnum * shdr_size,
|
|
978 sh_flags, Elf_Addr);
|
|
979 sh_addr = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
980 eow->shdrs + secnum * shdr_size,
|
|
981 sh_addr, Elf_Addr);
|
|
982 sh_link = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
983 eow->shdrs + secnum * shdr_size,
|
|
984 sh_link, Elf_Word);
|
|
985 sh_info = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
986 eow->shdrs + secnum * shdr_size,
|
|
987 sh_info, Elf_Word);
|
|
988 sh_addralign = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
989 eow->shdrs + secnum * shdr_size,
|
|
990 sh_addralign, Elf_Addr);
|
|
991 sh_entsize = ELF_FETCH_FIELD (attrs->type_functions, attrs->ei_class, Shdr,
|
|
992 eow->shdrs + secnum * shdr_size,
|
|
993 sh_entsize, Elf_Addr);
|
|
994 secnum++;
|
|
995 }
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
996
|
111
|
997 mask = sh_addralign - 1;
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
998 new_sh_offset = sh_offset + mask;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
999 new_sh_offset &= ~ mask;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1000 while (new_sh_offset > sh_offset)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1001 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1002 unsigned char zeroes[16];
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1003 size_t write;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1004
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1005 memset (zeroes, 0, sizeof zeroes);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1006 write = new_sh_offset - sh_offset;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1007 if (write > sizeof zeroes)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1008 write = sizeof zeroes;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1009 if (!simple_object_internal_write (descriptor, sh_offset, zeroes,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1010 write, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1011 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1012 sh_offset += write;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1013 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1014
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1015 sh_size = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1016 for (buffer = section->buffers; buffer != NULL; buffer = buffer->next)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1017 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1018 if (!simple_object_internal_write (descriptor, sh_offset + sh_size,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1019 ((const unsigned char *)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1020 buffer->buffer),
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1021 buffer->size, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1022 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1023 sh_size += buffer->size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1024 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1025
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1026 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
111
|
1027 sh_name, sh_type, sh_flags,
|
|
1028 sh_addr, sh_offset,
|
|
1029 sh_size, sh_link, sh_info,
|
|
1030 sh_addralign, sh_entsize,
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1031 &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1032 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1033
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1034 shdr_offset += shdr_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1035 sh_name += strlen (section->name) + 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1036 sh_offset += sh_size;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1037 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1038
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1039 if (!simple_object_elf_write_shdr (sobj, descriptor, shdr_offset,
|
111
|
1040 sh_name, SHT_STRTAB, 0, 0, sh_offset,
|
|
1041 sh_name + strlen (".shstrtab") + 1, 0, 0,
|
|
1042 1, 0, &errmsg, err))
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1043 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1044
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1045 /* .shstrtab has a leading zero byte. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1046 zero = 0;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1047 if (!simple_object_internal_write (descriptor, sh_offset, &zero, 1,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1048 &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1049 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1050 ++sh_offset;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1051
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1052 for (section = sobj->sections; section != NULL; section = section->next)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1053 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1054 size_t len;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1055
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1056 len = strlen (section->name) + 1;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1057 if (!simple_object_internal_write (descriptor, sh_offset,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1058 (const unsigned char *) section->name,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1059 len, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1060 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1061 sh_offset += len;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1062 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1063
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1064 if (!simple_object_internal_write (descriptor, sh_offset,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1065 (const unsigned char *) ".shstrtab",
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1066 strlen (".shstrtab") + 1, &errmsg, err))
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1067 return errmsg;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1068
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1069 return NULL;
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1070 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1071
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1072 /* Release the private data for an simple_object_write structure. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1073
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1074 static void
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1075 simple_object_elf_release_write (void *data)
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1076 {
|
111
|
1077 struct simple_object_elf_write *eow = (struct simple_object_elf_write *) data;
|
|
1078 if (eow->shdrs)
|
|
1079 XDELETE (eow->shdrs);
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1080 XDELETE (data);
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1081 }
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1082
|
111
|
1083 /* Copy all sections in an ELF file. */
|
|
1084
|
|
1085 static const char *
|
|
1086 simple_object_elf_copy_lto_debug_sections (simple_object_read *sobj,
|
|
1087 simple_object_write *dobj,
|
131
|
1088 char *(*pfn) (const char *),
|
111
|
1089 int *err)
|
|
1090 {
|
|
1091 struct simple_object_elf_read *eor =
|
|
1092 (struct simple_object_elf_read *) sobj->data;
|
|
1093 const struct elf_type_functions *type_functions = eor->type_functions;
|
|
1094 struct simple_object_elf_write *eow =
|
|
1095 (struct simple_object_elf_write *) dobj->data;
|
|
1096 unsigned char ei_class = eor->ei_class;
|
|
1097 size_t shdr_size;
|
|
1098 unsigned int shnum;
|
|
1099 unsigned char *shdrs;
|
|
1100 const char *errmsg;
|
|
1101 unsigned char *shstrhdr;
|
|
1102 size_t name_size;
|
|
1103 off_t shstroff;
|
|
1104 unsigned char *names;
|
|
1105 unsigned int i;
|
|
1106 int changed;
|
|
1107 int *pfnret;
|
|
1108 const char **pfnname;
|
131
|
1109 unsigned new_i;
|
|
1110 unsigned *sh_map;
|
|
1111 unsigned first_shndx = 0;
|
|
1112 unsigned int *symtab_indices_shndx;
|
111
|
1113
|
|
1114 shdr_size = (ei_class == ELFCLASS32
|
|
1115 ? sizeof (Elf32_External_Shdr)
|
|
1116 : sizeof (Elf64_External_Shdr));
|
|
1117
|
|
1118 /* Read the section headers. We skip section 0, which is not a
|
|
1119 useful section. */
|
|
1120
|
|
1121 shnum = eor->shnum;
|
|
1122 shdrs = XNEWVEC (unsigned char, shdr_size * (shnum - 1));
|
|
1123
|
|
1124 if (!simple_object_internal_read (sobj->descriptor,
|
|
1125 sobj->offset + eor->shoff + shdr_size,
|
|
1126 shdrs,
|
|
1127 shdr_size * (shnum - 1),
|
|
1128 &errmsg, err))
|
|
1129 {
|
|
1130 XDELETEVEC (shdrs);
|
|
1131 return errmsg;
|
|
1132 }
|
|
1133
|
|
1134 /* Read the section names. */
|
|
1135
|
|
1136 shstrhdr = shdrs + (eor->shstrndx - 1) * shdr_size;
|
|
1137 name_size = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1138 shstrhdr, sh_size, Elf_Addr);
|
|
1139 shstroff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1140 shstrhdr, sh_offset, Elf_Addr);
|
|
1141 names = XNEWVEC (unsigned char, name_size);
|
|
1142 if (!simple_object_internal_read (sobj->descriptor,
|
|
1143 sobj->offset + shstroff,
|
|
1144 names, name_size, &errmsg, err))
|
|
1145 {
|
|
1146 XDELETEVEC (names);
|
|
1147 XDELETEVEC (shdrs);
|
|
1148 return errmsg;
|
|
1149 }
|
|
1150
|
|
1151 pfnret = XNEWVEC (int, shnum);
|
|
1152 pfnname = XNEWVEC (const char *, shnum);
|
|
1153
|
131
|
1154 /* Map of symtab to index section. */
|
|
1155 symtab_indices_shndx = XCNEWVEC (unsigned int, shnum - 1);
|
|
1156
|
111
|
1157 /* First perform the callbacks to know which sections to preserve and
|
|
1158 what name to use for those. */
|
|
1159 for (i = 1; i < shnum; ++i)
|
|
1160 {
|
|
1161 unsigned char *shdr;
|
131
|
1162 unsigned int sh_name, sh_type;
|
111
|
1163 const char *name;
|
131
|
1164 char *ret;
|
111
|
1165
|
|
1166 shdr = shdrs + (i - 1) * shdr_size;
|
|
1167 sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1168 shdr, sh_name, Elf_Word);
|
|
1169 if (sh_name >= name_size)
|
|
1170 {
|
|
1171 *err = 0;
|
|
1172 XDELETEVEC (names);
|
|
1173 XDELETEVEC (shdrs);
|
|
1174 return "ELF section name out of range";
|
|
1175 }
|
|
1176
|
|
1177 name = (const char *) names + sh_name;
|
|
1178
|
131
|
1179 ret = (*pfn) (name);
|
|
1180 pfnret[i - 1] = ret == NULL ? -1 : 0;
|
|
1181 pfnname[i - 1] = ret == NULL ? name : ret;
|
|
1182 if (first_shndx == 0
|
|
1183 && pfnret[i - 1] == 0)
|
|
1184 first_shndx = i;
|
|
1185
|
|
1186 /* Remember the indexes of existing SHT_SYMTAB_SHNDX sections. */
|
|
1187 sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1188 shdr, sh_type, Elf_Word);
|
|
1189 if (sh_type == SHT_SYMTAB_SHNDX)
|
|
1190 {
|
|
1191 unsigned int sh_link;
|
|
1192 sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1193 shdr, sh_link, Elf_Word);
|
|
1194 symtab_indices_shndx[sh_link - 1] = i;
|
|
1195 /* Always discard the extended index sections, after
|
|
1196 copying it will not be needed. This way we don't need to
|
|
1197 update it and deal with the ordering constraints of
|
|
1198 processing the existing symtab and changing the index. */
|
|
1199 pfnret[i - 1] = -1;
|
|
1200 }
|
111
|
1201 }
|
|
1202
|
|
1203 /* Mark sections as preserved that are required by to be preserved
|
|
1204 sections. */
|
|
1205 do
|
|
1206 {
|
|
1207 changed = 0;
|
|
1208 for (i = 1; i < shnum; ++i)
|
|
1209 {
|
|
1210 unsigned char *shdr;
|
|
1211 unsigned int sh_type, sh_info, sh_link;
|
|
1212 off_t offset;
|
|
1213 off_t length;
|
|
1214
|
|
1215 shdr = shdrs + (i - 1) * shdr_size;
|
|
1216 sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1217 shdr, sh_type, Elf_Word);
|
|
1218 sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1219 shdr, sh_info, Elf_Word);
|
|
1220 sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1221 shdr, sh_link, Elf_Word);
|
|
1222 if (sh_type == SHT_GROUP)
|
|
1223 {
|
|
1224 /* Mark groups containing copied sections. */
|
|
1225 unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class,
|
|
1226 Shdr, shdr, sh_entsize,
|
|
1227 Elf_Addr);
|
|
1228 unsigned char *ent, *buf;
|
|
1229 int keep = 0;
|
|
1230 offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1231 shdr, sh_offset, Elf_Addr);
|
|
1232 length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1233 shdr, sh_size, Elf_Addr);
|
|
1234 buf = XNEWVEC (unsigned char, length);
|
|
1235 if (!simple_object_internal_read (sobj->descriptor,
|
|
1236 sobj->offset + offset, buf,
|
|
1237 (size_t) length, &errmsg, err))
|
|
1238 {
|
|
1239 XDELETEVEC (buf);
|
|
1240 XDELETEVEC (names);
|
|
1241 XDELETEVEC (shdrs);
|
|
1242 return errmsg;
|
|
1243 }
|
|
1244 for (ent = buf + entsize; ent < buf + length; ent += entsize)
|
|
1245 {
|
|
1246 unsigned sec = type_functions->fetch_Elf_Word (ent);
|
|
1247 if (pfnret[sec - 1] == 0)
|
|
1248 keep = 1;
|
|
1249 }
|
|
1250 if (keep)
|
|
1251 {
|
|
1252 changed |= (pfnret[sh_link - 1] == -1
|
|
1253 || pfnret[i - 1] == -1);
|
|
1254 pfnret[sh_link - 1] = 0;
|
|
1255 pfnret[i - 1] = 0;
|
|
1256 }
|
|
1257 }
|
|
1258 if (sh_type == SHT_RELA
|
|
1259 || sh_type == SHT_REL)
|
|
1260 {
|
|
1261 /* Mark relocation sections and symtab of copied sections. */
|
|
1262 if (pfnret[sh_info - 1] == 0)
|
|
1263 {
|
|
1264 changed |= (pfnret[sh_link - 1] == -1
|
|
1265 || pfnret[i - 1] == -1);
|
|
1266 pfnret[sh_link - 1] = 0;
|
|
1267 pfnret[i - 1] = 0;
|
|
1268 }
|
|
1269 }
|
|
1270 if (sh_type == SHT_SYMTAB)
|
|
1271 {
|
|
1272 /* Mark strings sections of copied symtabs. */
|
|
1273 if (pfnret[i - 1] == 0)
|
|
1274 {
|
|
1275 changed |= pfnret[sh_link - 1] == -1;
|
|
1276 pfnret[sh_link - 1] = 0;
|
|
1277 }
|
|
1278 }
|
|
1279 }
|
|
1280 }
|
|
1281 while (changed);
|
|
1282
|
131
|
1283 /* Compute a mapping of old -> new section numbers. */
|
|
1284 sh_map = XNEWVEC (unsigned, shnum);
|
|
1285 sh_map[0] = 0;
|
|
1286 new_i = 1;
|
|
1287 for (i = 1; i < shnum; ++i)
|
|
1288 {
|
|
1289 if (pfnret[i - 1] == -1)
|
|
1290 sh_map[i] = 0;
|
|
1291 else
|
|
1292 sh_map[i] = new_i++;
|
|
1293 }
|
|
1294 if (new_i - 1 >= SHN_LORESERVE)
|
|
1295 {
|
|
1296 *err = ENOTSUP;
|
|
1297 return "Too many copied sections";
|
|
1298 }
|
|
1299 eow->shdrs = XNEWVEC (unsigned char, shdr_size * (new_i - 1));
|
|
1300
|
111
|
1301 /* Then perform the actual copying. */
|
131
|
1302 new_i = 0;
|
111
|
1303 for (i = 1; i < shnum; ++i)
|
|
1304 {
|
|
1305 unsigned char *shdr;
|
|
1306 unsigned int sh_name, sh_type;
|
|
1307 const char *name;
|
|
1308 off_t offset;
|
|
1309 off_t length;
|
|
1310 simple_object_write_section *dest;
|
|
1311 off_t flags;
|
|
1312 unsigned char *buf;
|
|
1313
|
131
|
1314 if (pfnret[i - 1])
|
|
1315 continue;
|
|
1316
|
|
1317 new_i++;
|
111
|
1318 shdr = shdrs + (i - 1) * shdr_size;
|
|
1319 sh_name = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1320 shdr, sh_name, Elf_Word);
|
|
1321 if (sh_name >= name_size)
|
|
1322 {
|
|
1323 *err = 0;
|
|
1324 XDELETEVEC (names);
|
|
1325 XDELETEVEC (shdrs);
|
131
|
1326 XDELETEVEC (symtab_indices_shndx);
|
111
|
1327 return "ELF section name out of range";
|
|
1328 }
|
|
1329
|
131
|
1330 name = pfnname[i - 1];
|
111
|
1331 offset = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1332 shdr, sh_offset, Elf_Addr);
|
|
1333 length = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1334 shdr, sh_size, Elf_Addr);
|
|
1335 sh_type = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1336 shdr, sh_type, Elf_Word);
|
|
1337
|
131
|
1338 dest = simple_object_write_create_section (dobj, pfnname[i - 1],
|
|
1339 0, &errmsg, err);
|
111
|
1340 if (dest == NULL)
|
|
1341 {
|
|
1342 XDELETEVEC (names);
|
|
1343 XDELETEVEC (shdrs);
|
131
|
1344 XDELETEVEC (symtab_indices_shndx);
|
111
|
1345 return errmsg;
|
|
1346 }
|
|
1347
|
|
1348 /* Record the SHDR of the source. */
|
131
|
1349 memcpy (eow->shdrs + (new_i - 1) * shdr_size, shdr, shdr_size);
|
|
1350 shdr = eow->shdrs + (new_i - 1) * shdr_size;
|
111
|
1351
|
|
1352 /* Copy the data.
|
|
1353 ??? This is quite wasteful and ideally would be delayed until
|
|
1354 write_to_file (). Thus it questions the interfacing
|
|
1355 which eventually should contain destination creation plus
|
|
1356 writing. */
|
131
|
1357 buf = XNEWVEC (unsigned char, length);
|
|
1358 if (!simple_object_internal_read (sobj->descriptor,
|
|
1359 sobj->offset + offset, buf,
|
|
1360 (size_t) length, &errmsg, err))
|
|
1361 {
|
|
1362 XDELETEVEC (buf);
|
|
1363 XDELETEVEC (names);
|
|
1364 XDELETEVEC (shdrs);
|
|
1365 XDELETEVEC (symtab_indices_shndx);
|
|
1366 return errmsg;
|
|
1367 }
|
|
1368
|
145
|
1369 /* If we are processing .symtab purge any symbols
|
|
1370 in discarded sections. */
|
131
|
1371 if (sh_type == SHT_SYMTAB)
|
111
|
1372 {
|
131
|
1373 unsigned entsize = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1374 shdr, sh_entsize, Elf_Addr);
|
|
1375 unsigned strtab = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1376 shdr, sh_link, Elf_Word);
|
145
|
1377 size_t prevailing_name_idx = 0;
|
131
|
1378 unsigned char *ent;
|
|
1379 unsigned *shndx_table = NULL;
|
|
1380 /* Read the section index table if present. */
|
|
1381 if (symtab_indices_shndx[i - 1] != 0)
|
111
|
1382 {
|
131
|
1383 unsigned char *sidxhdr = shdrs + (strtab - 1) * shdr_size;
|
|
1384 off_t sidxoff = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1385 sidxhdr, sh_offset, Elf_Addr);
|
|
1386 size_t sidxsz = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1387 sidxhdr, sh_size, Elf_Addr);
|
|
1388 shndx_table = (unsigned *)XNEWVEC (char, sidxsz);
|
111
|
1389 simple_object_internal_read (sobj->descriptor,
|
131
|
1390 sobj->offset + sidxoff,
|
|
1391 (unsigned char *)shndx_table,
|
|
1392 sidxsz, &errmsg, err);
|
|
1393 }
|
145
|
1394
|
|
1395 /* Find a WEAK HIDDEN symbol which name we will use for removed
|
|
1396 symbols. We know there's a prevailing weak hidden symbol
|
|
1397 at the start of the .debug_info section. */
|
|
1398 for (ent = buf; ent < buf + length; ent += entsize)
|
|
1399 {
|
|
1400 unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
|
|
1401 Sym, ent,
|
|
1402 st_shndx, Elf_Half);
|
|
1403 unsigned char *st_info;
|
|
1404 unsigned char *st_other;
|
|
1405 if (ei_class == ELFCLASS32)
|
|
1406 {
|
|
1407 st_info = &((Elf32_External_Sym *)ent)->st_info;
|
|
1408 st_other = &((Elf32_External_Sym *)ent)->st_other;
|
|
1409 }
|
|
1410 else
|
|
1411 {
|
|
1412 st_info = &((Elf64_External_Sym *)ent)->st_info;
|
|
1413 st_other = &((Elf64_External_Sym *)ent)->st_other;
|
|
1414 }
|
|
1415 if (st_shndx == SHN_XINDEX)
|
|
1416 st_shndx = type_functions->fetch_Elf_Word
|
|
1417 ((unsigned char *)(shndx_table + (ent - buf) / entsize));
|
|
1418
|
|
1419 if (st_shndx != SHN_COMMON
|
|
1420 && !(st_shndx != SHN_UNDEF
|
|
1421 && st_shndx < shnum
|
|
1422 && pfnret[st_shndx - 1] == -1)
|
|
1423 && ELF_ST_BIND (*st_info) == STB_WEAK
|
|
1424 && *st_other == STV_HIDDEN)
|
|
1425 {
|
|
1426 prevailing_name_idx = ELF_FETCH_FIELD (type_functions,
|
|
1427 ei_class, Sym, ent,
|
|
1428 st_name, Elf_Word);
|
|
1429 break;
|
|
1430 }
|
|
1431 }
|
|
1432
|
131
|
1433 for (ent = buf; ent < buf + length; ent += entsize)
|
|
1434 {
|
|
1435 unsigned st_shndx = ELF_FETCH_FIELD (type_functions, ei_class,
|
|
1436 Sym, ent,
|
|
1437 st_shndx, Elf_Half);
|
|
1438 unsigned raw_st_shndx = st_shndx;
|
|
1439 unsigned char *st_info;
|
|
1440 unsigned char *st_other;
|
|
1441 int discard = 0;
|
|
1442 if (ei_class == ELFCLASS32)
|
|
1443 {
|
|
1444 st_info = &((Elf32_External_Sym *)ent)->st_info;
|
|
1445 st_other = &((Elf32_External_Sym *)ent)->st_other;
|
|
1446 }
|
|
1447 else
|
111
|
1448 {
|
131
|
1449 st_info = &((Elf64_External_Sym *)ent)->st_info;
|
|
1450 st_other = &((Elf64_External_Sym *)ent)->st_other;
|
|
1451 }
|
|
1452 if (st_shndx == SHN_XINDEX)
|
|
1453 st_shndx = type_functions->fetch_Elf_Word
|
|
1454 ((unsigned char *)(shndx_table + (ent - buf) / entsize));
|
145
|
1455 /* Eliminate all COMMONs - this includes __gnu_lto_slim
|
|
1456 which otherwise cause endless LTO plugin invocation.
|
|
1457 FIXME: remove the condition once we remove emission
|
|
1458 of __gnu_lto_slim symbol. */
|
131
|
1459 if (st_shndx == SHN_COMMON)
|
|
1460 discard = 1;
|
|
1461 /* We also need to remove symbols refering to sections
|
|
1462 we'll eventually remove as with fat LTO objects
|
|
1463 we otherwise get duplicate symbols at final link
|
|
1464 (with GNU ld, gold is fine and ignores symbols in
|
|
1465 sections marked as EXCLUDE). ld/20513 */
|
|
1466 else if (st_shndx != SHN_UNDEF
|
|
1467 && st_shndx < shnum
|
|
1468 && pfnret[st_shndx - 1] == -1)
|
|
1469 discard = 1;
|
|
1470
|
|
1471 if (discard)
|
|
1472 {
|
|
1473 /* Make discarded symbols undefined and unnamed
|
|
1474 in case it is local. */
|
|
1475 int bind = ELF_ST_BIND (*st_info);
|
|
1476 int other = STV_DEFAULT;
|
|
1477 if (bind == STB_LOCAL)
|
111
|
1478 {
|
131
|
1479 /* Make discarded local symbols unnamed and
|
|
1480 defined in the first prevailing section. */
|
|
1481 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1482 ent, st_name, Elf_Word, 0);
|
|
1483 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1484 ent, st_shndx, Elf_Half,
|
|
1485 sh_map[first_shndx]);
|
111
|
1486 }
|
|
1487 else
|
|
1488 {
|
131
|
1489 /* Make discarded global symbols hidden weak
|
145
|
1490 undefined and sharing a name of a prevailing
|
|
1491 symbol. */
|
131
|
1492 bind = STB_WEAK;
|
|
1493 other = STV_HIDDEN;
|
145
|
1494 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1495 ent, st_name, Elf_Word,
|
|
1496 prevailing_name_idx);
|
111
|
1497 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1498 ent, st_shndx, Elf_Half, SHN_UNDEF);
|
|
1499 }
|
131
|
1500 *st_other = other;
|
|
1501 *st_info = ELF_ST_INFO (bind, STT_NOTYPE);
|
|
1502 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1503 ent, st_value, Elf_Addr, 0);
|
|
1504 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1505 ent, st_size, Elf_Word, 0);
|
111
|
1506 }
|
131
|
1507 else if (raw_st_shndx < SHN_LORESERVE
|
|
1508 || raw_st_shndx == SHN_XINDEX)
|
|
1509 /* Remap the section reference. */
|
|
1510 ELF_SET_FIELD (type_functions, ei_class, Sym,
|
|
1511 ent, st_shndx, Elf_Half, sh_map[st_shndx]);
|
111
|
1512 }
|
131
|
1513 XDELETEVEC (shndx_table);
|
|
1514 }
|
|
1515 else if (sh_type == SHT_GROUP)
|
|
1516 {
|
|
1517 /* Remap section indices in groups and remove removed members. */
|
|
1518 unsigned char *ent, *dst;
|
|
1519 for (dst = ent = buf + 4; ent < buf + length; ent += 4)
|
111
|
1520 {
|
131
|
1521 unsigned shndx = type_functions->fetch_Elf_Word (ent);
|
|
1522 if (pfnret[shndx - 1] == -1)
|
|
1523 ;
|
|
1524 else
|
|
1525 {
|
|
1526 type_functions->set_Elf_Word (dst, sh_map[shndx]);
|
|
1527 dst += 4;
|
|
1528 }
|
111
|
1529 }
|
131
|
1530 /* Adjust the length. */
|
|
1531 length = dst - buf;
|
111
|
1532 }
|
131
|
1533
|
|
1534 errmsg = simple_object_write_add_data (dobj, dest,
|
|
1535 buf, length, 1, err);
|
|
1536 XDELETEVEC (buf);
|
|
1537 if (errmsg)
|
111
|
1538 {
|
131
|
1539 XDELETEVEC (names);
|
|
1540 XDELETEVEC (shdrs);
|
|
1541 XDELETEVEC (symtab_indices_shndx);
|
|
1542 return errmsg;
|
111
|
1543 }
|
|
1544
|
|
1545 flags = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1546 shdr, sh_flags, Elf_Addr);
|
131
|
1547 /* Remap the section references. */
|
|
1548 {
|
|
1549 unsigned int sh_info, sh_link;
|
|
1550 if (flags & SHF_INFO_LINK || sh_type == SHT_REL || sh_type == SHT_RELA)
|
|
1551 {
|
|
1552 sh_info = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1553 shdr, sh_info, Elf_Word);
|
|
1554 if (sh_info < SHN_LORESERVE
|
|
1555 || sh_info > SHN_HIRESERVE)
|
|
1556 sh_info = sh_map[sh_info];
|
|
1557 ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
|
1558 shdr, sh_info, Elf_Word, sh_info);
|
|
1559 }
|
|
1560 sh_link = ELF_FETCH_FIELD (type_functions, ei_class, Shdr,
|
|
1561 shdr, sh_link, Elf_Word);
|
|
1562 if (sh_link < SHN_LORESERVE
|
|
1563 || sh_link > SHN_HIRESERVE)
|
|
1564 sh_link = sh_map[sh_link];
|
|
1565 ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
|
1566 shdr, sh_link, Elf_Word, sh_link);
|
|
1567 }
|
|
1568 /* The debugobj doesn't contain any code, thus no trampolines.
|
|
1569 Even when the original object needs trampolines, debugobj
|
|
1570 doesn't. */
|
|
1571 if (strcmp (name, ".note.GNU-stack") == 0)
|
|
1572 flags &= ~SHF_EXECINSTR;
|
|
1573 /* Clear SHF_EXCLUDE on to be preserved sections. */
|
|
1574 flags &= ~SHF_EXCLUDE;
|
111
|
1575 ELF_SET_FIELD (type_functions, ei_class, Shdr,
|
|
1576 shdr, sh_flags, Elf_Addr, flags);
|
|
1577 }
|
|
1578
|
|
1579 XDELETEVEC (names);
|
|
1580 XDELETEVEC (shdrs);
|
|
1581 XDELETEVEC (pfnret);
|
|
1582 XDELETEVEC (pfnname);
|
131
|
1583 XDELETEVEC (symtab_indices_shndx);
|
|
1584 XDELETEVEC (sh_map);
|
111
|
1585
|
|
1586 return NULL;
|
|
1587 }
|
|
1588
|
|
1589
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1590 /* The ELF functions. */
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1591
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1592 const struct simple_object_functions simple_object_elf_functions =
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1593 {
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1594 simple_object_elf_match,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1595 simple_object_elf_find_sections,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1596 simple_object_elf_fetch_attributes,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1597 simple_object_elf_release_read,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1598 simple_object_elf_attributes_merge,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1599 simple_object_elf_release_attributes,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1600 simple_object_elf_start_write,
|
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1601 simple_object_elf_write_to_file,
|
111
|
1602 simple_object_elf_release_write,
|
|
1603 simple_object_elf_copy_lto_debug_sections
|
68
Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff
changeset
|
1604 };
|