4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
27 * dcom: Delete Comment
29 * This program demonstrates the use of libelf interface to
30 * copy the contents of one ELF file to create a new one.
31 * dcom creates a new ELF file using elf_begin(ELF_C_WRITE).
33 * In order to delete a section from an ELF file you must
34 * instead create a new ELF file and copy all but the 'selected'
35 * sections to the new ELF file. This is because libelf is
36 * unable to delete any sections from an ELF file, it can
39 * NOTE: While this program works fine for simple ELF objects,
40 * as they get more complex it may not properly update all of the
41 * fields required. This program is *only* an example of how
42 * to do this and not a complete program in itself.
51 #include <sys/types.h>
53 #include <sys/param.h>
56 static const char *CommentStr
= ".comment";
59 * Build a temporary file name that is in the
60 * same directory as the elf file being processed.
63 mkname(const char *bname
)
66 char buffer
[MAXPATHLEN
];
68 ptr
= strcpy(buffer
, bname
);
69 ptr
+= strlen(buffer
);
70 while (ptr
>= buffer
) {
81 return (tempnam(buffer
, 0));
85 delete_comment(Elf
*elf
, int fd
, const char *file
)
90 GElf_Ehdr ehdr
, tehdr
;
91 GElf_Phdr phdr
, tphdr
;
92 size_t shstrndx
, shnum
, phnum
;
93 int tfd
, *shndx
, ndx
= 1, off
= 0;
96 if (gelf_getehdr(elf
, &ehdr
) == NULL
) {
97 (void) fprintf(stderr
, "%s: elf_getehdr() failed: %s\n",
102 if (elf_getshdrnum(elf
, &shnum
) == -1) {
103 (void) fprintf(stderr
, "%s: elf_getshdrnum() failed: %s\n",
104 file
, elf_errmsg(0));
108 if (elf_getshdrstrndx(elf
, &shstrndx
) == -1) {
109 (void) fprintf(stderr
, "%s: elf_getshdrstrndx() failed: %s\n",
110 file
, elf_errmsg(0));
114 if (elf_getphdrnum(elf
, &phnum
) == -1) {
115 (void) fprintf(stderr
, "%s: elf_getphdrnum() failed: %s\n",
116 file
, elf_errmsg(0));
121 * shndx is an array used to map the current section
122 * indexes to the new section indexes.
124 shndx
= calloc(shnum
, sizeof (int));
126 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
130 * Do a string compare to examine each section header
131 * to see if it is a ".comment" section. If it is then
132 * this is the section we want to process.
134 if (gelf_getshdr(scn
, &shdr
) == NULL
) {
135 (void) fprintf(stderr
, "%s: elf_getshdr() failed: %s\n",
136 file
, elf_errmsg(0));
140 if (strcmp(CommentStr
, elf_strptr(elf
, shstrndx
,
141 shdr
.sh_name
)) == 0) {
146 * If the .comment section is part of a loadable
147 * segment then it can not be delted from the
150 if (shdr
.sh_addr
!= 0) {
151 (void) printf("%s: .comment section is "
152 "part of a loadable segment, it "
153 "cannot be deleted.\n", file
);
158 shndx
[ndx
] = ndx
- off
;
163 * obtain a unique file name and open a file descriptor
164 * pointing to that file.
166 tfile
= mkname(file
);
167 if ((tfd
= open(tfile
, O_RDWR
| O_CREAT
, 0600)) == -1) {
173 * Create a new ELF to duplicate the ELF file into.
175 if ((telf
= elf_begin(tfd
, ELF_C_WRITE
, 0)) == NULL
) {
176 (void) fprintf(stderr
, "elf_begin(ELF_C_WRITE) failed: %s\n",
181 if (gelf_newehdr(telf
, gelf_getclass(elf
)) == NULL
) {
182 (void) fprintf(stderr
, "%s: elf_newehdr() failed: %s\n",
183 file
, elf_errmsg(0));
187 if (gelf_getehdr(telf
, &tehdr
) == NULL
) {
188 (void) fprintf(stderr
, "%s: elf_getehdr() failed: %s\n",
189 file
, elf_errmsg(0));
196 while ((scn
= elf_nextscn(elf
, scn
)) != NULL
) {
198 Elf_Data
*data
, *tdata
;
199 GElf_Shdr shdr
, tshdr
;
201 if (shndx
[ndx
] == -1) {
207 * Duplicate all but the .comment section in the
210 if (gelf_getshdr(scn
, &shdr
) == NULL
) {
211 (void) fprintf(stderr
, "%s: elf_getshdr() failed: %s\n",
212 file
, elf_errmsg(0));
216 if ((tscn
= elf_newscn(telf
)) == NULL
) {
217 (void) fprintf(stderr
, "%s: elf_newscn() failed: %s\n",
218 file
, elf_errmsg(0));
222 if (gelf_getshdr(tscn
, &tshdr
) == NULL
) {
223 (void) fprintf(stderr
, "%s: elf_getshdr() failed: %s\n",
224 file
, elf_errmsg(0));
229 tshdr
.sh_link
= shndx
[shdr
.sh_link
];
232 * The relocation sections sh_info field also contains
233 * a section index that needs to be adjusted. This is
234 * the only section who's sh_info field contains
235 * a section index according to the ABI.
237 * If their are non-ABI sections who's sh_info field
238 * contains section indexes they will not properly
239 * be updated by this routine.
241 if (shdr
.sh_type
== SHT_REL
)
242 tshdr
.sh_info
= shndx
[ndx
];
245 * Flush the changes to the underlying elf32 or elf64
248 (void) gelf_update_shdr(tscn
, &tshdr
);
250 if ((data
= elf_getdata(scn
, 0)) == NULL
) {
251 (void) fprintf(stderr
, "%s: elf_getdata() failed: %s\n",
252 file
, elf_errmsg(0));
256 if ((tdata
= elf_newdata(tscn
)) == NULL
) {
257 (void) fprintf(stderr
, "%s: elf_newdata() failed: %s\n",
258 file
, elf_errmsg(0));
267 if (shndx
[shstrndx
] < SHN_LORESERVE
)
268 tehdr
.e_shstrndx
= shndx
[shstrndx
];
274 * 'ELF Extended Sections' are enabled - we must
275 * store the shstrndx in Shdr[0].sh_link
277 if ((_scn
= elf_getscn(telf
, 0)) == NULL
) {
278 (void) fprintf(stderr
, "%s: elf_getscn() failed: %s\n",
279 file
, elf_errmsg(0));
283 if (gelf_getshdr(_scn
, &shdr0
) == NULL
) {
284 (void) fprintf(stderr
, "%s: elf_getshdr() failed: %s\n",
285 file
, elf_errmsg(0));
289 tehdr
.e_shstrndx
= SHN_XINDEX
;
290 shdr0
.sh_link
= shndx
[shstrndx
];
291 (void) gelf_update_shdr(_scn
, &shdr0
);
293 (void) gelf_update_ehdr(telf
, &tehdr
);
298 * Duplicate all program headers contained in the ELF file.
301 if (gelf_newphdr(telf
, phnum
) == NULL
) {
302 (void) fprintf(stderr
, "%s: elf_newphdr() failed: %s\n",
303 file
, elf_errmsg(0));
306 for (ndx
= 0; ndx
< (int)phnum
; ndx
++) {
307 if (gelf_getphdr(elf
, ndx
, &phdr
) == NULL
||
308 gelf_getphdr(telf
, ndx
, &tphdr
) == NULL
) {
309 (void) fprintf(stderr
,
310 "%s: elf_getphdr() failed: %s\n",
311 file
, elf_errmsg(0));
315 (void) gelf_update_phdr(telf
, ndx
, &tphdr
);
320 * The new Elf file has now been fully described to libelf.
321 * elf_update() will construct the new Elf file and write
324 if (elf_update(telf
, ELF_C_WRITE
) == -1) {
325 (void) fprintf(stderr
, "elf_update() failed: %s\n",
327 (void) elf_end(telf
);
331 (void) elf_end(telf
);
334 * set new files permissions to the original files
337 (void) fstat(fd
, &sbuf
);
338 (void) fchmod(tfd
, sbuf
.st_mode
);
343 * delete the original file and rename the new file
344 * to the orignal file.
346 (void) rename(tfile
, file
);
350 main(int argc
, char ** argv
)
355 (void) printf("usage: %s elf_file ...\n", argv
[0]);
360 * Initialize the elf library, must be called before elf_begin()
363 if (elf_version(EV_CURRENT
) == EV_NONE
) {
364 (void) fprintf(stderr
, "elf_version() failed: %s\n",
369 for (i
= 1; i
< argc
; i
++) {
376 if ((fd
= open(elf_fname
, O_RDONLY
)) == -1) {
382 * Attempt to open an Elf descriptor Read/Write
385 if ((elf
= elf_begin(fd
, ELF_C_READ
, 0)) == NULL
) {
386 (void) fprintf(stderr
, "elf_begin() failed: %s\n",
393 * Determine what kind of elf file this is:
395 if (elf_kind(elf
) != ELF_K_ELF
) {
397 * can only delete comment sections from
400 (void) printf("%s not of type ELF_K_ELF. "
401 "elf_kind == %d\n", elf_fname
, elf_kind(elf
));
403 delete_comment(elf
, fd
, elf_fname
);