/*
* 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
*
*/
#include <errno.h>
#include "alist.h"
#include "mcs.h"
#include "extern.h"
#include "gelf.h"
/*
* Type used to pass state information for the current
* file between routines.
*/
typedef struct {
int Sect_exists;
int notesegndx;
int notesctndx;
/* retain old offset, else 0 */
char *new_sec_string;
} file_state_t;
/*
* Function prototypes.
*/
static void
static void copy_elf_file_to_temp_ar_file(int, Elf_Arhdr *, char *);
file_state_t *);
int
{
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 */ {
elf_getbase(elf));
return (FAILURE);
}
if (cur_filenm != NULL)
}
}
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) {
return (FAILURE);
} else {
}
}
}
if (err != 0) {
return (FAILURE);
}
/* copy ar_temp_file to FILE */
return (error);
}
static int
{
int x;
/*
* Initialize
*/
return (FAILURE);
}
return (FAILURE);
}
/* Initialize per-file state */
state.Sect_exists = 0;
} else if (x != DONT_BUILD && x != FAILURE) {
}
}
/* Release any dynamicaly allocated buffers */
if (x == DONT_BUILD)
return (DONT_BUILD);
else
return (error);
}
static int
{
char *temp_name;
GElf_Xword x;
unsigned int i, scn_index;
state->Sect_exists = 0;
return (FAILURE);
}
return (FAILURE);
}
scn = 0;
scn_index = 1;
char *name;
return (FAILURE);
}
/*
* Note: If the object has problems, name
* may be set to NULL by the following.
*/
else
}
}
/*
* 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.
*/
state->Sect_exists++;
}
/*
* Any of the following section types should
* also be removed (if possible) if invoked via
* the 'strip' command.
*/
state->Sect_exists++;
}
/*
* Zap this file ?
*/
state->Sect_exists++;
}
/*
* Remember the note section index so that we can
* reset the NOTE segment offset to point to it. Depending
* on the operation being carried out, the note section may
* be assigned a new location in the resulting ELF
* image, and the program header needs to reflect that.
*
* There can be multiple contiguous note sections in
* an object, referenced by a single NOTE segment. We
* want to be sure and remember the one referenced by
* the program header, and not one of the others.
*/
/*
* 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 (state->Sect_exists == 0)
++state->Sect_exists;
/*
* Can I remove section header
* string table ?
*/
AFTER)) {
++(cmd_info->no_of_nulled);
if (state->Sect_exists == 0)
++state->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;
return (FAILURE);
}
}
}
/*
* 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 (state->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
flags, ACT_DELETE);
}
/*
* 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().
*/
(acc != 0))
}
sinfo++;
}
}
}
/*
* I know that the file has been modified.
* A new file need to be created.
*/
return (SUCCESS);
}
static int
{
/* section's name */
unsigned int c = 0;
int fdtmp;
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
return (FAILURE);
}
/* initialize dst_ehdr */
/*
* If we are removing the header string table section,
* remove the reference to it from the ELF header.
*/
/*
* flush the changes to the ehdr so the ident
* array and header string table index are 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.
*/
0)
else
else
}
return (FAILURE);
}
/*
* SHT_{DYNSYM, SYMTAB} might need some change, as
* they may contain section symbols that reference
* removed sections. SHT_SUNW_LDYNSYM does not
* contain section symbols, and therefore does not
* have this issue.
*/
src_shdr.sh_entsize != 0 &&
(cmd_info->no_of_delete != 0 ||
cmd_info->no_of_nulled != 0)) {
char *new_sym;
}
/* CSTYLED */
for (c = 0; c < no_of_symbols; c++) {
i = &state->
if (((int)i->secno !=
DELETED) &&
i->secno;
} else {
/* BEGIN CSTYLED */
SHT_SYMTAB) {
/*
* 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.
*/
}
/* END CSTYLED */
}
}
(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))) {
}
for (c = 0; c < entcnt; c++) {
i = &state->
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 (!state->Sect_exists &&
!= IN) ||
(x != PRIOR))) {
}
/* put original data plus new data in section */
/* LINTED */
}
/*
* Compute offsets.
*/
/*
* Compute section offset.
*/
if (dst_shdr.sh_addralign != 0) {
r = new_offset %
if (r)
new_offset +=
sh_addralign - r;
}
} else {
}
}
/* flush changes */
}
scn_no++;
}
/*
* This is the real new section.
*/
return (FAILURE);
}
else
dst_shdr.sh_entsize = 0;
return (FAILURE);
}
}
}
/*
* 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;
}
/*
* remember the note SEGMENTS index so that we can
* re-set it's p_offset later if needed.
*/
state->notesegndx = i;
}
return (SUCCESS);
}
static void
int fdartmp,
char *cur_file)
{
char *buf;
int fdtmp3;
}
if ((buf =
}
}
(unsigned)sizeof (struct ar_hdr)) !=
(unsigned)sizeof (struct ar_hdr)) {
}
cur_file);
}
cur_file);
}
}
static void
int fd,
int fdartmp,
char *cur_file,
{
char *file_buf;
sizeof (struct ar_hdr)) {
}
if ((file_buf =
prog);
}
}
}
}
}
}
/*
* Replace contents of file
*
* entry:
* ofd - Open file descriptor for file fname
* fname - Name of file being processed
* temp_file_name - Address of pointer to temporary
* file containing new contents for fname.
*
* exit:
* The contents of the file given by temp_file->tmp_name are
* copied to the file fname. The temporary file is
* unlinked, and temp_file reset.
*/
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().
*/
if ((buf =
prog);
}
}
}
}
}
}
/*
* clean
*/
if (mmap_status == 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;
}
}
}
}
/*
* Update the contents of SHT_GROUP if needed
*/
static 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.
*/
continue;
/*
* Need to generate the updated data buffer
*/
prog);
}
prog);
}
j = 1;
for (i = 1; i < num; i++) {
ngrpdata[j++] =
}
}
}
}