file.c revision 5aefb6555731130ca4fd295960123d71f2d21fe8
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1988 AT&T
* All Rights Reserved
*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <errno.h>
#include "mcs.h"
#include "extern.h"
#include "gelf.h"
static int Sect_exists = 0;
static int notesegndx = -1;
static int notesctndx = -1;
static Seg_Table *b_e_seg_table;
static section_info_table *sec_table;
/* set to retain old offset, else 0 */
static char *new_sec_string = NULL;
#define MMAP_USED 1
#define MMAP_UNUSED 2
/*
* Function prototypes.
*/
static void copy_file(int, char *, char *);
static void
static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *);
static void post_process(Cmd_Info *);
int
{
char *cur_filenm = NULL;
int code = 0;
int ar_file = 0;
int fdartmp;
int fd;
int oflag;
else
return (FAILURE);
}
/*
* Note, elf_begin requires ELF_C_READ even if MIGHT_CHK is in effect.
* libelf does not allow elf_begin() with ELF_C_RDWR when processing
* archive file members. Because we are limited to ELF_C_READ use, any
* ELF data modification must be provided by updating a copy of
* the data, rather than updating the original file data.
*/
cmd = ELF_C_READ;
return (FAILURE);
}
ar_file = 1;
}
/* write magic string to artmpfile */
}
}
} else {
ar_file = 0;
}
/*
* Holds temporary file;
* if archive, holds the current member file if it has an ehdr,
* and there were no errors in
* processing the object file.
*/
if (ar_file) /* get header info */ {
return (FAILURE);
}
if (cur_filenm != NULL)
PLAIN_ERROR, (char *)0,
prog);
}
}
FAILURE) {
if (!ar_file) {
return (FAILURE);
} else {
error++;
}
if (code == DONT_BUILD)
else
}
} else {
/*
* decide what to do with non-ELF file
*/
if (!ar_file) {
PLAIN_ERROR, (char *)0,
prog, cur_filenm);
return (FAILURE);
} else {
}
}
}
if (err != 0) {
PLAIN_ERROR, (char *)0,
return (FAILURE);
}
/* copy ar_temp_file to FILE */
return (error);
}
static int
{
int x;
/*
* Initialize
*/
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
FAILURE) {
PLAIN_ERROR, (char *)0,
} else if (x != DONT_BUILD && x != FAILURE) {
PLAIN_ERROR, (char *)0,
}
}
if (x == DONT_BUILD)
return (DONT_BUILD);
else
return (error);
}
static int
{
char *temp_name;
GElf_Xword x;
unsigned int i, scn_index;
Sect_exists = 0;
return (FAILURE);
}
return (FAILURE);
}
scn = 0;
scn_index = 1;
char *name;
return (FAILURE);
} else {
name = "_@@@###";
}
else
PLAIN_ERROR, (char *)0, prog);
}
}
/*
* If the target section is pointed by a section
* holding relocation infomation, then the
* pointing section would be useless if the
* target section is removed.
*/
if (phnum == 0)
else
}
}
data = 0;
return (FAILURE);
}
/*
* Check if this section is a candidate for
* action to be processes.
*/
/*
* This flag just shows that there was a
* candidate.
*/
Sect_exists++;
}
/*
* Any of the following section types should
* also be removed (if possible) if invoked via
* the 'strip' command.
*/
Sect_exists++;
}
/*
* Zap this file ?
*/
Sect_exists++;
}
/*
* Remeber the note sections index so that we can
* reset the NOTE segments offset to point to it.
*
* It may have been assigned a new location in the
* resulting output elf image.
*/
/*
* If this section satisfies the condition,
* apply the actions specified.
*/
}
/*
* If I am strip command, determine if symtab can go or not.
*/
}
}
scn_index++;
sinfo++;
}
/*
* If there were any errors traversing the file,
* just return error.
*/
if (ret != 0)
return (FAILURE);
/*
* Remove symbol table if possible
*/
++(cmd_info->no_of_nulled);
if (Sect_exists == 0)
++Sect_exists;
/*
* Can I remove section header
* string table ?
*/
++(cmd_info->no_of_nulled);
if (Sect_exists == 0)
++Sect_exists;
}
}
/*
* If I only printed the contents, then
* just report so.
*/
return (DONT_BUILD); /* don't bother creating a new file */
/* since the file has not changed */
/*
* I might need to add a new section. Check it.
*/
int act = 0;
if (new_sec_string == NULL)
return (FAILURE);
(void) strcat(new_sec_string,
}
}
}
/*
* If I did not append any new sections, and I did not
*/
return (DONT_BUILD);
/*
* Found at least one section which was processed.
* Deleted or Appended or Compressed.
*/
if (Sect_exists) {
/*
* First, handle the deleted sections.
*/
if (cmd_info->no_of_delete != 0 ||
cmd_info->no_of_nulled != 0) {
int acc = 0;
int rel_idx;
/*
* Handle relocation/target
* sections.
*/
for (i = 1; i < shnum; i++) {
sinfo++;
if (rel_idx == 0)
continue;
/*
* If I am removed, then remove my
* target section.
*/
else
}
/*
* I am not removed. Check if my target is
* removed or nulled. If so, let me try to
* remove my self.
*/
else
}
}
/*
* Now, take care of DELETED sections
*/
for (i = 1; i < shnum; i++) {
acc++;
/*
* The SHT_GROUP section which this section
* is a member may be able to be removed.
* See post_process().
*/
} else {
/*
* The data buffer of SHT_GROUP this section
* is a member needs to be updated.
* See post_process().
*/
}
sinfo++;
}
}
}
/*
* I know that the file has been modified.
* A new file need to be created.
*/
return (SUCCESS);
}
static int
{
int new_sh_name = 0; /* to hold the offset for the new */
/* section's name */
size_t no_of_symbols = 0;
unsigned int c = 0;
int fdtmp;
GElf_Off new_offset = 0, r;
return (FAILURE);
}
return (FAILURE);
}
prog, elftmpfile);
return (FAILURE);
}
prog, elftmpfile);
return (FAILURE);
}
return (FAILURE);
}
/* initialize dst_ehdr */
/*
* flush the changes to the ehdr so the
* ident array is filled in.
*/
return (FAILURE);
}
/* LINTED */
/* LINTED */
/* LINTED */
}
if (x == AFTER)
}
scn_no = 1;
/* If section should be copied to new file NOW */
return (FAILURE);
}
/*
* Update link and info fields
* The sh_link field may have special values so
* check them first.
*/
else
else
}
return (FAILURE);
}
/* SHT_{DYNSYM, SYMTAB} might need some change */
src_shdr.sh_entsize != 0 &&
(cmd_info->no_of_delete != 0 ||
cmd_info->no_of_nulled != 0)) {
char *new_sym;
PLAIN_ERROR, (char *)0, prog);
}
/* CSTYLED */
for (c = 0; c < no_of_symbols; c++) {
if (((int)i->secno !=
DELETED) &&
i->secno;
else {
/*
* The section which
* this * symbol relates
* to is removed.
* There is no way to
* specify this fact,
* just change the shndx
* to 1.
*/
else {
/*
* If this is in a
* .dynsym, NULL it out.
*/
}
}
}
(void) gelf_update_sym(elf_data, c,
&csym);
}
}
/* update SHT_SYMTAB_SHNDX */
(src_shdr.sh_entsize != 0) &&
((cmd_info->no_of_delete != 0) ||
(cmd_info->no_of_nulled != 0))) {
PLAIN_ERROR, (char *)0, prog);
}
for (c = 0; c < entcnt; c++) {
if (((int)i->secno !=
DELETED) &&
else
newshndx[c] =
oldshndx[c];
} else
newshndx[c] =
oldshndx[c];
}
}
/*
* If the section is to be updated,
* do so.
*/
/*
* The section is updated,
* but the position is not too
* good. Need to NULL this out.
*/
(cmd_info->no_of_moved)++;
}
} else {
/*
* The section is positioned AFTER,
* or there are no segments.
* It is safe to update this section.
*/
}
}
/* add new section name to shstrtab? */
else if (!Sect_exists &&
(new_sec_string != NULL) &&
(x != PRIOR))) {
PLAIN_ERROR, (char *)0, prog);
}
/* put original data plus new data in section */
sect_len + 1);
/* LINTED */
}
/*
* Compute offsets.
*/
/*
* Compute section offset.
*/
if (dst_shdr.sh_addralign != 0) {
r = new_offset %
if (r)
new_offset +=
dst_shdr.sh_addralign - r;
}
} else {
if (nobits_table[scn_no] == 0)
}
if (nobits_table[scn_no] == 0)
}
}
scn_no++;
}
/*
* This is the real new section.
*/
return (FAILURE);
}
else
dst_shdr.sh_entsize = 0;
return (FAILURE);
}
PLAIN_ERROR, (char *)0,
prog);
}
}
/*
* If there are sections which needed to be moved,
* then do it here.
*/
if (cmd_info->no_of_moved != 0) {
int cnt;
continue;
NULL) {
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
else
else
return (FAILURE);
}
}
}
/*
* In the event that the position of the sting table has changed,
* as a result of deleted sections, update the ehdr->e_shstrndx.
*/
} else {
/*
* If shstrndx requires 'Extended ELF Sections'
* then it is stored in shdr[0].sh_link
*/
return (FAILURE);
}
}
}
/* UPDATE location of program header table */
r = new_offset % align;
if (r)
new_offset += align - r;
}
/* UPDATE location of section header table */
r = new_offset % align;
if (r)
new_offset += align - r;
}
/*
* The NOTE segment is the one segment whos
* sections might get moved by mcs processing.
* Make sure that the NOTE segments offset points
* to the .note section.
*/
/* LINTED */
} else {
}
}
}
/* copy ehdr changes back into real ehdr */
return (FAILURE);
}
return (SUCCESS);
}
/*
* Search through PHT saving the beginning and ending segment offsets
*/
static int
{
unsigned int i;
if ((b_e_seg_table = (Seg_Table *)
PLAIN_ERROR, (char *)0,
prog);
}
/*
* remember the note SEGMENTS index so that we can
* re-set it's p_offset later if needed.
*/
notesegndx = i;
}
return (SUCCESS);
}
static void
int fdartmp,
char *cur_file)
{
char *buf;
int fdtmp3;
prog, elftmpfile);
}
if ((buf =
PLAIN_ERROR, (char *)0,
prog);
}
}
(unsigned)mem_header->ar_uid,
(unsigned)mem_header->ar_gid,
(unsigned)mem_header->ar_mode,
(unsigned)sizeof (struct ar_hdr)) !=
(unsigned)sizeof (struct ar_hdr)) {
}
}
}
}
static void
int fd,
int fdartmp,
char *cur_file,
{
char *file_buf;
(unsigned)mem_header->ar_uid,
(unsigned)mem_header->ar_gid,
(unsigned)mem_header->ar_mode,
sizeof (struct ar_hdr)) {
}
if ((file_buf =
PLAIN_ERROR, (char *)0,
prog);
}
}
}
}
PLAIN_ERROR, (char *)0,
PLAIN_ERROR, (char *)0,
cur_file);
}
}
static void
{
int i;
int fdtmp2;
char *buf;
for (i = 0; signum[i]; i++) /* started writing, cannot interrupt */
}
/*
* Get the contents of the updated file.
* First try mmap()'ing. If mmap() fails,
* then use the malloc() and read().
*/
i = MMAP_USED;
if ((buf =
PLAIN_ERROR, (char *)0,
prog);
}
}
i = MMAP_UNUSED;
}
}
}
}
/*
* clean
*/
if (i == MMAP_USED)
else
}
static uint64_t
{
int i;
if (mem_search)
else
return (IN);
return (PRIOR);
}
return (AFTER);
}
static uint64_t
{
/*
* If the section is not a NOTE section and it has no
* virtual address then it is not part of a mapped segment.
*/
}
static void
{
/*
* Initialize command info
*/
cmd_info->no_of_moved = 0;
if ((sec_table = (section_info_table *)
sizeof (section_info_table))) == NULL) {
PLAIN_ERROR, (char *)0,
prog);
}
PLAIN_ERROR, (char *)0,
prog);
}
if ((nobits_table = (int64_t *)
PLAIN_ERROR, (char *)0,
prog);
}
}
/*
* Update the contents of SHT_GROUP if needed
*/
void
{
/*
* If no change is required, then return.
*/
return;
/*
* If SHF_GROUP sections were removed, we might need to
* remove SHT_GROUP sections.
*/
int deleted = 0;
continue;
grpcnt = 0;
for (i = 1; i < num; i++) {
grpcnt++;
}
/*
* All members in this SHT_GROUP were removed.
* We can remove this SHT_GROUP.
*/
if (grpcnt == 0) {
(cmd_info->no_of_delete)++;
deleted = 1;
}
}
/*
* If we deleted a SHT_GROUP section,
* we need to reasign section numbers.
*/
if (deleted) {
sno = 1;
sno2 = 1;
sno++;
}
}
}
/*
* Now we can update data buffers of the
* SHT_GROUP sections.
*/
plnp = 0;
if (plnp)
continue;
/*
* Need to generate the updated data buffer
*/
PLAIN_ERROR, (char *)0,
prog);
}
PLAIN_ERROR, (char *)0,
prog);
}
j = 1;
for (i = 1; i < num; i++) {
}
}
}
if (plnp)
}