177 lines
3.6 KiB
C
Executable File
177 lines
3.6 KiB
C
Executable File
/* Copyright (c) 1988 AT&T */
|
|
/* All Rights Reserved */
|
|
|
|
/* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T */
|
|
/* The copyright notice above does not evidence any */
|
|
/* actual or intended publication of such source code. */
|
|
|
|
#pragma ident "@(#)getdata.c 1.6 94/10/21 SMI" /* SVr4.0 1.16 */
|
|
|
|
/*LINTLIBRARY*/
|
|
|
|
#ifdef __STDC__
|
|
#pragma weak elf_getdata = _elf_getdata
|
|
#endif
|
|
|
|
|
|
#include "syn.h"
|
|
#include <stdlib.h>
|
|
#include "libelf.h"
|
|
#include "decl.h"
|
|
#include "error.h"
|
|
|
|
|
|
/* Convert data from file format to memory format.
|
|
*/
|
|
|
|
|
|
static const size_t align[] =
|
|
{
|
|
1, /* ELF_T_BYTE */
|
|
sizeof(Elf32), /* ELF_T_ADDR */
|
|
sizeof(Elf32), /* ELF_T_DYN */
|
|
sizeof(Elf32), /* ELF_T_EHDR */
|
|
sizeof(Elf32_Half), /* ELF_T_HALF */
|
|
sizeof(Elf32), /* ELF_T_OFF */
|
|
sizeof(Elf32), /* ELF_T_PHDR */
|
|
sizeof(Elf32), /* ELF_T_RELA */
|
|
sizeof(Elf32), /* ELF_T_REL */
|
|
sizeof(Elf32), /* ELF_T_SHDR */
|
|
sizeof(Elf32), /* ELF_T_SWORD */
|
|
sizeof(Elf32), /* ELF_T_SYM */
|
|
sizeof(Elf32), /* ELF_T_WORD */
|
|
sizeof(Elf32), /* ELF_T_VERDEF */
|
|
sizeof(Elf32), /* ELF_T_VERNEED */
|
|
};
|
|
|
|
#define Nalign (sizeof(align)/sizeof(align[0]))
|
|
|
|
|
|
Elf_Data *
|
|
elf_getdata(scn, data)
|
|
register Elf_Scn *scn;
|
|
Elf_Data *data;
|
|
{
|
|
register Dnode *d = (Dnode *)data;
|
|
register Elf *elf;
|
|
Elf_Data src;
|
|
|
|
/* trap null args, end of list, previous buffer.
|
|
* SHT_NULL sections have no buffer list, so they
|
|
* fall out here too.
|
|
*/
|
|
|
|
if (scn == 0)
|
|
return 0;
|
|
if (d == 0)
|
|
d = scn->s_hdnode;
|
|
else
|
|
d = d->db_next;
|
|
if (scn->s_err != 0)
|
|
{
|
|
_elf_err = scn->s_err;
|
|
return 0;
|
|
}
|
|
if (d == 0)
|
|
return 0;
|
|
if (d->db_scn != scn)
|
|
{
|
|
_elf_err = EREQ_DATA;
|
|
return 0;
|
|
}
|
|
if (d->db_myflags & DBF_READY)
|
|
return &d->db_data;
|
|
elf = scn->s_elf;
|
|
|
|
/* Prepare return buffer. The data come from the memory
|
|
* image of the file. "Empty" regions get an empty buffer.
|
|
*
|
|
* Only sections of an ELF_C_READ file can be not READY here.
|
|
* Furthermore, the input file must have been cooked or
|
|
* frozen by now. Translate cooked files in place if possible.
|
|
*/
|
|
|
|
d->db_data.d_version = _elf_work;
|
|
if (d->db_off == 0 || d->db_fsz == 0)
|
|
{
|
|
d->db_myflags |= DBF_READY;
|
|
return &d->db_data;
|
|
}
|
|
|
|
{
|
|
Elf32_Shdr *sh = scn->s_shdr;
|
|
size_t sz = sh->sh_entsize;
|
|
Elf_Type t = d->db_data.d_type;
|
|
|
|
if (t != ELF_T_BYTE
|
|
&& sz > 1
|
|
&& sz != elf32_fsize(t, 1, elf->ed_version))
|
|
{
|
|
_elf_err = EFMT_ENTSZ;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* validate the region
|
|
*/
|
|
|
|
if (d->db_off < 0
|
|
|| d->db_off >= elf->ed_fsz
|
|
|| elf->ed_fsz - d->db_off < d->db_fsz)
|
|
{
|
|
_elf_err = EFMT_DATA;
|
|
return 0;
|
|
}
|
|
|
|
/* set up translation buffers and validate
|
|
*/
|
|
|
|
src.d_buf = (Elf_Void *)(elf->ed_ident + d->db_off);
|
|
src.d_size = d->db_fsz;
|
|
src.d_type = d->db_data.d_type;
|
|
src.d_version = elf->ed_version;
|
|
if (_elf_vm(elf, (size_t)d->db_off, d->db_fsz) != OK_YES)
|
|
return 0;
|
|
|
|
/* decide where to put destination
|
|
*/
|
|
|
|
switch (elf->ed_status)
|
|
{
|
|
case ES_COOKED:
|
|
if ((size_t)d->db_data.d_type >= Nalign)
|
|
{
|
|
_elf_err = EBUG_COOKTYPE;
|
|
return 0;
|
|
}
|
|
|
|
/* If the destination size (memory) is at least as
|
|
* big as the source size (file), reuse the space.
|
|
*/
|
|
|
|
if (d->db_data.d_size <= src.d_size
|
|
&& d->db_off % align[d->db_data.d_type] == 0)
|
|
{
|
|
d->db_data.d_buf = (Elf_Void *)(elf->ed_ident + d->db_off);
|
|
break;
|
|
}
|
|
/*FALLTHRU*/
|
|
case ES_FROZEN:
|
|
if ((d->db_buf = malloc(d->db_data.d_size)) == 0)
|
|
{
|
|
_elf_err = EMEM_DATA;
|
|
return 0;
|
|
}
|
|
d->db_data.d_buf = d->db_buf;
|
|
break;
|
|
|
|
default:
|
|
_elf_err = EBUG_COOKSTAT;
|
|
return 0;
|
|
}
|
|
if (elf32_xlatetom(&d->db_data, &src, elf->ed_encode) == 0)
|
|
return 0;
|
|
d->db_myflags |= DBF_READY;
|
|
return &d->db_data;
|
|
}
|