Esempio n. 1
0
 void encoding(T state, Encoding* obj) {
   if(obj->nil_p() || (!CBOOL(ascii_only()) && obj->ascii_compatible())) {
     ascii_only(cNil);
     num_chars(nil<Fixnum>());
     valid_encoding(cNil);
   }
   if(byte_size() == 0 && !obj->nil_p() && obj->ascii_compatible()) {
     ascii_only(cTrue);
     num_chars(Fixnum::from(0));
     valid_encoding(cTrue);
   }
   encoding(obj);
   state->memory()->write_barrier(this, obj);
 }
Esempio n. 2
0
    void encoding_from(STATE, String* other) {
      encoding(other->encoding());
      state->memory()->write_barrier(this, encoding());

      if(other->ascii_only()->true_p()) {
        ascii_only(cTrue);
      } else {
        ascii_only(cNil);
      }
      if(other->valid_encoding()->true_p()) {
        valid_encoding(cTrue);
      } else {
        valid_encoding(cNil);
      }
    }
Esempio n. 3
0
/*
 * destination buffer size
 */
size_t
_elf32_xltsize(const Elf_Data *src, unsigned dv, unsigned encode, int tof) {
    Elf_Type type = src->d_type;
    unsigned sv = src->d_version;
    xlator op;

    if (!valid_version(sv) || !valid_version(dv)) {
	seterr(ERROR_UNKNOWN_VERSION);
	return (size_t)-1;
    }
    if (tof) {
	/*
	 * Encoding doesn't really matter (the translator only looks at
	 * the source, which resides in memory), but we need a proper
	 * encoding to select a translator...
	 */
	encode = ELFDATA2LSB;
    }
    else if (!valid_encoding(encode)) {
	seterr(ERROR_UNKNOWN_ENCODING);
	return (size_t)-1;
    }
    if (!valid_type(type)) {
	seterr(ERROR_UNKNOWN_TYPE);
	return (size_t)-1;
    }
    if (!(op = translator(sv, dv, encode, type, tof))) {
	seterr(ERROR_UNKNOWN_TYPE);
	return (size_t)-1;
    }
    return (*op)(NULL, src->d_buf, src->d_size);
}
Esempio n. 4
0
/*
 * direction-independent translation
 */
static Elf_Data*
elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
    Elf_Type type;
    int dv;
    int sv;
    size_t dsize;
    size_t tmp;
    xlator op;

    if (!src || !dst) {
	return NULL;
    }
    if (!src->d_buf || !dst->d_buf) {
	seterr(ERROR_NULLBUF);
	return NULL;
    }
    if (!valid_encoding(encode)) {
	seterr(ERROR_UNKNOWN_ENCODING);
	return NULL;
    }
    sv = src->d_version;
    dv = dst->d_version;
    if (!valid_version(sv) || !valid_version(dv)) {
	seterr(ERROR_UNKNOWN_VERSION);
	return NULL;
    }
    type = src->d_type;
    if (!valid_type(type)) {
	seterr(ERROR_UNKNOWN_TYPE);
	return NULL;
    }
    op = translator(sv, dv, encode, type, tof);
    if (!op) {
	seterr(ERROR_UNKNOWN_TYPE);
	return NULL;
    }
    dsize = (*op)(NULL, src->d_buf, src->d_size);
    if (dsize == (size_t)-1) {
	return NULL;
    }
    if (dst->d_size < dsize) {
	seterr(ERROR_DST2SMALL);
	return NULL;
    }
    if (dsize) {
	tmp = (*op)(dst->d_buf, src->d_buf, src->d_size);
	if (tmp == (size_t)-1) {
	    return NULL;
	}
	elf_assert(tmp == dsize);
    }
    dst->d_size = dsize;
    dst->d_type = type;
    return dst;
}
Esempio n. 5
0
/*
 * direction-independent translation
 */
static Elf_Data*
elf32_xlate(Elf_Data *dst, const Elf_Data *src, unsigned encode, int tof) {
    size_t ssize, dsize, count;
    Elf_Type type;
    int sv, dv;
    xlator op;

    if (!src || !dst) {
	return NULL;
    }
    if (!src->d_buf || !dst->d_buf) {
	seterr(ERROR_NULLBUF);
	return NULL;
    }
    if (!valid_encoding(encode)) {
	seterr(ERROR_UNKNOWN_ENCODING);
	return NULL;
    }
    sv = src->d_version;
    dv = dst->d_version;
    if (!valid_version(sv) || !valid_version(dv)) {
	seterr(ERROR_UNKNOWN_VERSION);
	return NULL;
    }
    type = src->d_type;
    if (!valid_type(type)) {
	seterr(ERROR_UNKNOWN_TYPE);
	return NULL;
    }
    ssize = _fmsize(ELFCLASS32, sv, type, 1 - tof);
    dsize = _fmsize(ELFCLASS32, dv, type, tof);
    op = translator(sv, dv, encode, type, tof);
    if (!ssize || !dsize || !op) {
	seterr(ERROR_UNKNOWN_TYPE);
	return NULL;
    }
    count = src->d_size / ssize;
    if (dst->d_size < count * dsize) {
	seterr(ERROR_DST2SMALL);
	return NULL;
    }
    if (count) {
	(*op)(dst->d_buf, src->d_buf, count);
    }
    dst->d_size = count * dsize;
    dst->d_type = type;
    return dst;
}
Esempio n. 6
0
static off_t
_elf64_layout(Elf *elf, unsigned *flag) {
    int layout = (elf->e_elf_flags & ELF_F_LAYOUT) == 0;
    Elf64_Ehdr *ehdr = (Elf64_Ehdr*)elf->e_ehdr;
    size_t off = 0;
    unsigned version;
    unsigned encoding;
    size_t align_addr;
    size_t entsize;
    unsigned shnum;
    Elf_Scn *scn;

    *flag = elf->e_elf_flags | elf->e_phdr_flags;

    if ((version = ehdr->e_version) == EV_NONE) {
	version = EV_CURRENT;
    }
    if (!valid_version(version)) {
	seterr(ERROR_UNKNOWN_VERSION);
	return -1;
    }
    if ((encoding = ehdr->e_ident[EI_DATA]) == ELFDATANONE) {
	encoding = native_encoding;
    }
    if (!valid_encoding(encoding)) {
	seterr(ERROR_UNKNOWN_ENCODING);
	return -1;
    }
    entsize = _fsize(ELFCLASS64, version, ELF_T_EHDR);
    elf_assert(entsize);
    rewrite(ehdr->e_ehsize, entsize, elf->e_ehdr_flags);
    off = entsize;

    align_addr = _fsize(ELFCLASS64, version, ELF_T_ADDR);
    elf_assert(align_addr);

    if (elf->e_phnum) {
	entsize = _fsize(ELFCLASS64, version, ELF_T_PHDR);
	elf_assert(entsize);
	if (layout) {
	    align(off, align_addr);
	    rewrite(ehdr->e_phoff, off, elf->e_ehdr_flags);
	    off += elf->e_phnum * entsize;
	}
	else {
	    off = max(off, ehdr->e_phoff + elf->e_phnum * entsize);
	}
    }
    else {
	entsize = 0;
	if (layout) {
	    rewrite(ehdr->e_phoff, 0, elf->e_ehdr_flags);
	}
    }
    rewrite(ehdr->e_phnum, elf->e_phnum, elf->e_ehdr_flags);
    rewrite(ehdr->e_phentsize, entsize, elf->e_ehdr_flags);

    for (scn = elf->e_scn_1, shnum = 0; scn; scn = scn->s_link, ++shnum) {
	Elf64_Shdr *shdr = &scn->s_shdr64;
	size_t scn_align = 1;
	off_t len;

	elf_assert(scn->s_index == shnum);

	*flag |= scn->s_scn_flags;

	if (scn->s_index == SHN_UNDEF) {
	    rewrite(shdr->sh_entsize, 0, scn->s_shdr_flags);
	    if (layout) {
		rewrite(shdr->sh_offset, 0, scn->s_shdr_flags);
		rewrite(shdr->sh_size, 0, scn->s_shdr_flags);
		rewrite(shdr->sh_addralign, 0, scn->s_shdr_flags);
	    }
	    *flag |= scn->s_shdr_flags;
	    continue;
	}
	if (shdr->sh_type == SHT_NULL) {
	    *flag |= scn->s_shdr_flags;
	    continue;
	}

	len = scn_data_layout(scn, version, shdr->sh_type, &scn_align, flag);
	if (len == -1) {
	    return -1;
	}

	/*
	 * Never override the program's choice.
	 */
	if (shdr->sh_entsize == 0) {
	    entsize = scn_entsize(elf, version, shdr->sh_type);
	    if (entsize > 1) {
		rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags);
	    }
	}

	if (layout) {
	    align(off, scn_align);
	    rewrite(shdr->sh_offset, off, scn->s_shdr_flags);
	    rewrite(shdr->sh_size, (size_t)len, scn->s_shdr_flags);
	    rewrite(shdr->sh_addralign, scn_align, scn->s_shdr_flags);

	    if (shdr->sh_type != SHT_NOBITS) {
		off += (size_t)len;
	    }
	}
	else if ((size_t)len > shdr->sh_size) {
	    seterr(ERROR_SCN2SMALL);
	    return -1;
	}
	else {
	    Elf_Scn *scn2;
	    size_t end1, end2;

	    end1 = shdr->sh_offset;
	    if (shdr->sh_type != SHT_NOBITS) {
		end1 += shdr->sh_size;
	    }
	    if (shdr->sh_offset < off) {
		/*
		 * check for overlapping sections
		 */
		for (scn2 = elf->e_scn_1; scn2; scn2 = scn2->s_link) {
		    if (scn2 == scn) {
			break;
		    }
		    end2 = scn2->s_shdr64.sh_offset;
		    if (scn2->s_shdr64.sh_type != SHT_NOBITS) {
			end2 += scn2->s_shdr64.sh_size;
		    }
		    if (end1 > scn2->s_shdr64.sh_offset
		     && end2 > shdr->sh_offset) {
			seterr(ERROR_SCN_OVERLAP);
			return -1;
		    }
		}
	    }
	    if (off < end1) {
		off = end1;
	    }
	}
	*flag |= scn->s_shdr_flags;
    }

    if (shnum) {
	entsize = _fsize(ELFCLASS64, version, ELF_T_SHDR);
	elf_assert(entsize);
	if (layout) {
	    align(off, align_addr);
	    rewrite(ehdr->e_shoff, off, elf->e_ehdr_flags);
	    off += shnum * entsize;
	}
	else {
	    off = max(off, ehdr->e_shoff + shnum * entsize);
	}
    }
    else {
	entsize = 0;
	if (layout) {
	    rewrite(ehdr->e_shoff, 0, elf->e_ehdr_flags);
	}
    }
    if (shnum >= SHN_LORESERVE) {
	Elf_Scn *scn = elf->e_scn_1;
	Elf64_Shdr *shdr = &scn->s_shdr64;

	elf_assert(scn->s_index == 0);
	rewrite(shdr->sh_size, shnum, scn->s_shdr_flags);
	*flag |= scn->s_shdr_flags;
	shnum = 0;
    }
    rewrite(ehdr->e_shnum, shnum, elf->e_ehdr_flags);
    rewrite(ehdr->e_shentsize, entsize, elf->e_ehdr_flags);

    rewrite(ehdr->e_ident[EI_MAG0], ELFMAG0, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_MAG1], ELFMAG1, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_MAG2], ELFMAG2, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_MAG3], ELFMAG3, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_CLASS], ELFCLASS64, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_DATA], encoding, elf->e_ehdr_flags);
    rewrite(ehdr->e_ident[EI_VERSION], version, elf->e_ehdr_flags);
    rewrite(ehdr->e_version, version, elf->e_ehdr_flags);

    *flag |= elf->e_ehdr_flags;

    return off;
}