in contrib/elftoolchain/elfcopy/ascii.c [46:195]
static int ihex_read(const char *line, char *type, uint64_t *addr,
uint64_t *num, uint8_t *data, size_t *sz);
static void ihex_write(int ofd, int type, uint64_t addr, uint64_t num,
const void *buf, size_t sz);
static void ihex_write_00(int ofd, uint64_t addr, const void *buf, size_t sz);
static void ihex_write_01(int ofd);
static void ihex_write_04(int ofd, uint16_t addr);
static void ihex_write_05(int ofd, uint64_t e_entry);
static struct section *new_data_section(struct elfcopy *ecp, int sec_index,
uint64_t off, uint64_t addr);
static int read_num(const char *line, int *len, uint64_t *num, size_t sz,
int *checksum);
static int srec_read(const char *line, char *type, uint64_t *addr,
uint8_t *data, size_t *sz);
static void srec_write(int ofd, char type, uint64_t addr, const void *buf,
size_t sz);
static void srec_write_symtab(int ofd, const char *ofn, Elf *e, Elf_Scn *scn,
GElf_Shdr *sh);
static void srec_write_S0(int ofd, const char *ofn);
static void srec_write_Sd(int ofd, char dr, uint64_t addr, const void *buf,
size_t sz, size_t rlen);
static void srec_write_Se(int ofd, uint64_t e_entry, int forceS3);
static void write_num(char *line, int *len, uint64_t num, size_t sz,
int *checksum);
#define _LINE_BUFSZ 1024
#define _DATA_BUFSZ 256
/*
* Convert ELF object to S-Record.
*/
void
create_srec(struct elfcopy *ecp, int ifd, int ofd, const char *ofn)
{
Elf *e;
Elf_Scn *scn;
Elf_Data *d;
GElf_Ehdr eh;
GElf_Shdr sh;
uint64_t max_addr;
size_t rlen;
int elferr, addr_sz;
char dr;
if ((e = elf_begin(ifd, ELF_C_READ, NULL)) == NULL)
errx(EXIT_FAILURE, "elf_begin() failed: %s",
elf_errmsg(-1));
/* Output a symbol table for `symbolsrec' target. */
if (!strncmp(ecp->otgt, "symbolsrec", strlen("symbolsrec"))) {
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s",
elf_errmsg(-1));
(void) elf_errno();
continue;
}
if (sh.sh_type != SHT_SYMTAB)
continue;
srec_write_symtab(ofd, ofn, e, scn, &sh);
break;
}
}
if (ecp->flags & SREC_FORCE_S3)
dr = '3';
else {
/*
* Find maximum address size in the first iteration.
*/
max_addr = 0;
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s",
elf_errmsg(-1));
(void) elf_errno();
continue;
}
if ((sh.sh_flags & SHF_ALLOC) == 0 ||
sh.sh_type == SHT_NOBITS ||
sh.sh_size == 0)
continue;
if ((uint64_t) sh.sh_addr > max_addr)
max_addr = sh.sh_addr;
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
if (max_addr <= 0xFFFF)
dr = '1';
else if (max_addr <= 0xFFFFFF)
dr = '2';
else
dr = '3';
}
if (ecp->flags & SREC_FORCE_LEN) {
addr_sz = dr - '0' + 1;
if (ecp->srec_len < 1)
rlen = 1;
else if (ecp->srec_len + addr_sz + 1 > 255)
rlen = 255 - (addr_sz + 1);
else
rlen = ecp->srec_len;
} else
rlen = 16;
/* Generate S0 record which contains the output filename. */
srec_write_S0(ofd, ofn);
/* Generate S{1,2,3} data records for section data. */
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
if (gelf_getshdr(scn, &sh) == NULL) {
warnx("gelf_getshdr failed: %s", elf_errmsg(-1));
(void) elf_errno();
continue;
}
if ((sh.sh_flags & SHF_ALLOC) == 0 ||
sh.sh_type == SHT_NOBITS ||
sh.sh_size == 0)
continue;
if (sh.sh_addr > 0xFFFFFFFF) {
warnx("address space too big for S-Record file");
continue;
}
(void) elf_errno();
if ((d = elf_getdata(scn, NULL)) == NULL) {
elferr = elf_errno();
if (elferr != 0)
warnx("elf_getdata failed: %s", elf_errmsg(-1));
continue;
}
if (d->d_buf == NULL || d->d_size == 0)
continue;
srec_write_Sd(ofd, dr, sh.sh_addr, d->d_buf, d->d_size, rlen);
}
elferr = elf_errno();
if (elferr != 0)
warnx("elf_nextscn failed: %s", elf_errmsg(elferr));
/* Generate S{7,8,9} end of block record. */
if (gelf_getehdr(e, &eh) == NULL)
errx(EXIT_FAILURE, "gelf_getehdr() failed: %s",
elf_errmsg(-1));
srec_write_Se(ofd, eh.e_entry, ecp->flags & SREC_FORCE_S3);
}