コード例 #1
0
ファイル: rpath.c プロジェクト: dilos/dilos-userland
/*
 * Returns the offset of the specified string from within
 * the given string table.
 *
 * entry:
 *	dynsec - Dynamic section descriptor
 *	strsec - Descriptor for string table associated with dynamic section
 *	dyn_strpad - DT_SUNW_STRPAD element from dynamic section
 *	str - String we are looking for.
 *
 * exit:
 *	On success, the offset of the given string within the string
 *	table is returned. If the string does not exist within the table,
 *	but there is a valid DT_SUNW_STRPAD reserved section, then we
 *	add the string, and update the dynamic section STRPAD element
 *	to reflect the space we use.
 *
 *	This routine does not return on failure.
 */
static GElf_Word
dynstr_insert(Cache *dynsec, Cache *strsec, dyn_elt_t *dyn_strpad,
    const char *str)
{
	GElf_Word	ins_off;	/* Table offset to 1st reserved byte */
	char		*s;		/* ptr to strings within table */
	GElf_Word	len;		/* Length of str inc. NULL byte */
	GElf_Word	tail_ign;	/* # reserved bytes at end of strtab */


	tail_ign = dyn_strpad->seen ? dyn_strpad->dyn.d_un.d_val : 0;

	/* Does the string already exist in the string table? */
	if (sec_findstr(strsec, tail_ign, str, &len))
		return (len);

	/*
	 * The desired string does not already exist. Do we have
	 * room to add it?
	 */
	len = strlen(str) + 1;
	if (!dyn_strpad->seen || (len > dyn_strpad->dyn.d_un.d_val))
		msg_fatal("[%d]%s: String table does not have room "
		    "to add string\n", strsec->c_shdr.sh_link,
		    strsec->c_name);


	/*
	 * We will add the string at the first byte of the reserved NULL
	 * area at the end. The DT_SUNW_STRPAD dynamic element gives us
	 * the size of that reserved space.
	 */
	ins_off = strsec->c_shdr.sh_size - tail_ign;
	s = ((char *)strsec->c_data->d_buf) + ins_off;

	/* Announce the operation */
	msg_debug("[%d]%s[%d]: Using %d/%d byes from reserved area to "
	    "add string: %s\n", strsec->c_shdr.sh_link, strsec->c_name,
	    ins_off, len, (int)dyn_strpad->dyn.d_un.d_val, str);

	/*
	 * Copy the string into the pad area at the end, and
	 * mark the data area as dirty so libelf will flush our
	 * changes to the string data.
	 */
	(void) strncpy(s, str, dyn_strpad->dyn.d_un.d_val);
	(void) elf_flagdata(strsec->c_data, ELF_C_SET, ELF_F_DIRTY);

	/* Update the DT_STRPAD dynamic entry */
	dyn_strpad->dyn.d_un.d_val -= len;
	if (gelf_update_dyn(dynsec->c_data, dyn_strpad->ndx,
	    &dyn_strpad->dyn) == 0)
		msg_elf("gelf_update_dyn");

	return (ins_off);
}
コード例 #2
0
ファイル: test-flag-nobits.c プロジェクト: AMCScarface/misc
int
main (int argc, char **argv)
{
  if (argc != 2)
    abort ();

  elf_version (EV_CURRENT);

  int fd = open64 (argv[1], O_RDONLY);
  Elf *stripped = elf_begin (fd, ELF_C_READ, NULL);

  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn (stripped, scn)) != NULL)
    elf_flagdata (elf_getdata (scn, NULL), ELF_C_SET, ELF_F_DIRTY);
}
コード例 #3
0
void saveSharedLibrary::saveMutations(char *textInsn){

	memcpy(textData->d_buf, textInsn, textData->d_size);	
	elf_flagdata(textData,ELF_C_SET,ELF_F_DIRTY);

}
コード例 #4
0
ファイル: rpath.c プロジェクト: dilos/dilos-userland
int
main(int argc, char **argv)
{
	int		c, ndx;
	int		readonly;
	int		fd;
	const char	*file;
	const char	*runpath;
	Elf		*elf;
	GElf_Ehdr	ehdr;
	size_t		shstrndx, shnum;
	Elf_Scn		*scn;
	Elf_Data	*data;
	char		*shnames = NULL;
	Cache		*cache, *_cache;
	Cache		*dynsec, *strsec;
	GElf_Word	numdyn;
	dyn_elt_t	rpath_elt;
	dyn_elt_t	runpath_elt;
	dyn_elt_t	strpad_elt;
	dyn_elt_t	flags_1_elt;
	dyn_elt_t	null_elt;
	int		changed = 0;


	opterr = 0;
	while ((c = getopt(argc, argv, "dr")) != EOF) {
		switch (c) {
		case 'd':
			d_flg = 1;
			break;

		case 'r':
			r_flg = 1;
			break;

		case '?':
			msg_usage();
		}
	}

	/*
	 * The first plain argument is the file name, and is required.
	 * The second plain argument is the runpath, and is optional.
	 * If no runpath is given, we print the current runpath to stdout
	 * and exit. If it is present, we modify the ELF file to use it.
	 */
	argc = argc - optind;
	argv += optind;
	if ((argc < 1) || (argc > 2))
		msg_usage();
	if ((argc == 2) && r_flg)
		msg_usage();

	readonly = (argc == 1) && !r_flg;
	file = argv[0];
	if (!readonly)
		runpath = argv[1];

	if ((fd = open(file, readonly ? O_RDONLY : O_RDWR)) == -1)
		msg_fatal("unable to open file: %s: %s\n",
		    file, strerror(errno));

	(void) elf_version(EV_CURRENT);
	elf = elf_begin(fd, readonly ? ELF_C_READ : ELF_C_RDWR, NULL);
	if (elf == NULL)
		msg_elf("elf_begin");

	/* We only handle standalone ELF files */
	switch (elf_kind(elf)) {
	case ELF_K_AR:
		msg_fatal("unable to edit ELF archive: %s\n", file);
		break;
	case ELF_K_ELF:
		break;
	default:
		msg_fatal("unable to edit non-ELF file: %s\n", file);
		break;
	}

	if (gelf_getehdr(elf, &ehdr) == NULL)
		msg_elf("gelf_getehdr");

	if (elf_getshnum(elf, &shnum) == 0)
		msg_elf("elf_getshnum");

	if (elf_getshstrndx(elf, &shstrndx) == 0)
		msg_elf("elf_getshstrndx");

	/*
	 * Obtain the .shstrtab data buffer to provide the required section
	 * name strings.
	 */
	if ((scn = elf_getscn(elf, shstrndx)) == NULL)
		msg_elf("elf_getscn");
	if ((data = elf_getdata(scn, NULL)) == NULL)
		msg_elf("elf_getdata");
	shnames = data->d_buf;

	/*
	 * Allocate a cache to maintain a descriptor for each section.
	 */
	if ((cache = malloc(shnum * sizeof (Cache))) == NULL)
		msg_fatal("unable to allocate section cache: %s\n",
		    strerror(errno));
	bzero(cache, sizeof (cache[0]));
	cache->c_name = "";
	_cache = cache + 1;

	/*
	 * Fill in cache with information for each section, and
	 * locate the dynamic section.
	 */
	dynsec = strsec = NULL;
	for (ndx = 1, scn = NULL; scn = elf_nextscn(elf, scn);
	    ndx++, _cache++) {
		_cache->c_ndx = ndx;
		if (gelf_getshdr(scn, &_cache->c_shdr) == NULL)
			msg_elf("gelf_getshdr");
		_cache->c_data = elf_getdata(scn, NULL);
		_cache->c_name = shnames + _cache->c_shdr.sh_name;
		if (_cache->c_shdr.sh_type == SHT_DYNAMIC) {
			dynsec = _cache;
			numdyn = dynsec->c_shdr.sh_size /
			    dynsec->c_shdr.sh_entsize;
			msg_debug("[%d]%s: dynamic section\n",
			    ndx, _cache->c_name);
		}
	}

	/*
	 * If we got a dynamic section, locate the string table.
	 * If not, we can't continue.
	 */
	if (dynsec == NULL)
		msg_fatal("file lacks a dynamic section: %s\n", file);
	strsec = &cache[dynsec->c_shdr.sh_link];
	msg_debug("[%d]%s: dynamic string table section\n",
	    strsec->c_ndx, strsec->c_name);

	/*
	 * History Lesson And Strategy:
	 *
	 * This routine handles both DT_RPATH and DT_RUNPATH entries, altering
	 * either or both if they are present.
	 *
	 * The original SYSV ABI only had DT_RPATH, and the runtime loader used
	 * it to search for things in the following order:
	 *
	 *	DT_RPATH, LD_LIBRARY_PATH, defaults
	 *
	 * Solaris did not follow this rule. Environment variables should
	 * supersede everything else, so we have always deviated from the
	 * ABI and and instead search in the order
	 *
	 *	LD_LIBRARY_PATH, DT_RPATH, defaults
	 *
	 * Other Unix variants initially followed the ABI, but in recent years
	 * realized that it was a mistake. Hence, DT_RUNPATH was invented,
	 * with the search order:
	 *
	 *	LD_LIBRARY_PATH, DT_RUNPATH, defaults
	 *
	 * So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both
	 * are present (which does happen), we set them both to the new
	 * value. If either one is present, we set that one. If neither is
	 * present, and we have a spare DT_NULL slot, we create a DT_RUNPATH.
	 */

	/*
	 * Examine the dynamic section to determine the index for
	 *	- DT_RPATH
	 *	- DT_RUNPATH
	 *	- DT_SUNW_STRPAD
	 *	- DT_NULL, and whether there are any extra DT_NULL slots
	 */
	dyn_elt_init(&rpath_elt);
	dyn_elt_init(&runpath_elt);
	dyn_elt_init(&strpad_elt);
	dyn_elt_init(&flags_1_elt);
	dyn_elt_init(&null_elt);
	for (ndx = 0; ndx < numdyn; ndx++) {
		GElf_Dyn	dyn;

		if (gelf_getdyn(dynsec->c_data, ndx, &dyn) == NULL)
			msg_elf("gelf_getdyn");

		switch (dyn.d_tag) {
		case DT_NULL:
			/*
			 * Remember the state of the first DT_NULL. If there
			 * are more than one (i.e. the first one is not
			 * in the final spot), and there is no runpath, then
			 * we will turn the first one into a DT_RUNPATH.
			 */
			if (!null_elt.seen) {
				dyn_elt_save(&null_elt, ndx, &dyn);
				msg_debug("[%d]%s[%d]: DT_NULL\n",
				    dynsec->c_ndx, dynsec->c_name, ndx);
			}
			break;

		case DT_RPATH:
			dyn_elt_save(&rpath_elt, ndx, &dyn);
			msg_debug("[%d]%s[%d]: DT_RPATH: %s\n",
			    dynsec->c_ndx, dynsec->c_name, ndx,
			    DYN_ELT_STRING(&rpath_elt, strsec));
			break;

		case DT_RUNPATH:
			dyn_elt_save(&runpath_elt, ndx, &dyn);
			msg_debug("[%d]%s[%d]: DT_RUNPATH: %s\n",
			    dynsec->c_ndx, dynsec->c_name, ndx,
			    DYN_ELT_STRING(&runpath_elt, strsec));
			break;

		case DT_SUNW_STRPAD:
			dyn_elt_save(&strpad_elt, ndx, &dyn);
			msg_debug("[%d]%s[%d]: DT_STRPAD: %d\n",
			    dynsec->c_ndx, dynsec->c_name, ndx,
			    (int)strpad_elt.dyn.d_un.d_val);
			break;

		case DT_FLAGS_1:
			dyn_elt_save(&flags_1_elt, ndx, &dyn);
			break;
		}
	}

	/*
	 * If this is a readonly session, then print the existing
	 * runpath and exit. DT_RPATH and DT_RUNPATH should have
	 * the same value, so we arbitrarily favor DT_RUNPATH.
	 */
	if (readonly) {
		if (runpath_elt.seen)
			(void) printf("%s\n",
			    DYN_ELT_STRING(&runpath_elt, strsec));
		else if (rpath_elt.seen)
			(void) printf("%s\n",
			    DYN_ELT_STRING(&rpath_elt, strsec));
		else
			msg_debug("ELF file does not have a runpath: %s\n",
			    file);
		return (0);
	}


	/* Edit the file, either to remove the runpath or to add/modify it */
	if (r_flg) {
		if (!(runpath_elt.seen || rpath_elt.seen))
			msg_debug("[%d]%s: no runpath found\n",
			    dynsec->c_ndx, dynsec->c_name);
		else
			changed = remove_runpath(dynsec, numdyn);
	} else {
		changed = new_runpath(runpath, dynsec, numdyn, strsec,
		    &rpath_elt, &runpath_elt, &strpad_elt, &null_elt);
	}

	if (changed) {
		/*
		 * If possible, set the DF_1_EDITED flag, indicating that
		 * this file has been edited after the fact.
		 */
		if (flags_1_elt.seen) {
			flags_1_elt.dyn.d_un.d_val |= DF_1_EDITED;
		} else if (null_elt.seen && (null_elt.ndx < (numdyn - 1))) {
			msg_debug("[%d]%s: No existing flags_1 entry to "
			    "modify. Will use extra DT_NULL in slot [%d] \n",
			    dynsec->c_ndx, dynsec->c_name, null_elt.ndx);
			flags_1_elt.seen = 1;
			flags_1_elt.ndx = null_elt.ndx;
			flags_1_elt.dyn.d_tag = DT_FLAGS_1;
			flags_1_elt.dyn.d_un.d_val = DF_1_EDITED;
		}
		if (flags_1_elt.seen) {
			msg_debug("[%d]%s[%d]: Set DF_1_EDITED flag\n",
			    dynsec->c_ndx, dynsec->c_name, flags_1_elt.ndx);
			if (gelf_update_dyn(dynsec->c_data, flags_1_elt.ndx,
			    &flags_1_elt.dyn) == 0)
				msg_elf("gelf_update_dyn");
		}

		/*
		 * Mark the data area as dirty so libelf will flush our
		 * changes to the dynamic section data.
		 */
		(void) elf_flagdata(dynsec->c_data, ELF_C_SET, ELF_F_DIRTY);

		/* Flush the file to disk */
		if (elf_update(elf, ELF_C_WRITE) == -1)
			msg_elf("elf_update");
		(void) close(fd);
		(void) elf_end(elf);
	}
	return (0);
}
コード例 #5
0
static int replaceAMDILSection(Elf* e, int nStream, MWCALtargetEnum target)
{
    Elf_Scn* scn = NULL;
    size_t shstrndx = 0;
    static const int verbose = 0;
    static const int verboseDebug = 0;

    /* Get section index of section containing the string table of section names */
    if (elf_getshdrstrndx(e, &shstrndx) != 0)
    {
        mw_printf("elf_getshdrstrndx failed: %s\n", elf_errmsg(-1));
        return 1;
    }

    /* Iterate through all the sections */
    while ((scn = elf_nextscn(e, scn)))
    {
        Elf32_Shdr* shdr;
        const char* name;

        /* Get the header for this section */
        shdr = elf32_getshdr(scn);
        if (!shdr)
        {
            mw_printf("elf32_getshdr() failed: %s\n", elf_errmsg(-1));
            return 1;
        }

        /* Look up the name of the section in the string table */
        name = elf_strptr(e, shstrndx, shdr->sh_name);
        if (!name)
        {
            mw_printf("elf_strptr() failed: %s\n", elf_errmsg(-1));
            return 1;
        }

        /*
        if (strstr(name, ".rodata") != NULL)
        {
            Elf_Data* data = elf_getdata(scn, NULL);


            FILE* f = fopen("rodata_section.bin", "wb");
            if (f)
            {
                fwrite(data->d_buf, 1, data->d_size, f);
                fclose(f);
            }
            else
            {
                perror("Failed to open file");
            }

            size_t roSize;
            char* r770RO = mwReadFileWithSize("rodata_section_RV770.bin", &roSize);
            assert(r770RO);

            data->d_buf = r770RO;
            data->d_size = roSize;


            if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (elf_update(e, ELF_C_NULL) < 0)
            {
                mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1));
                return 1;
            }
        }
        */

        if (strstr(name, ".amdil") != NULL)
        {
            int uavId;
            const char* uavComment;
            Elf_Data* data;

            data = elf_getdata(scn, NULL);
            if (!data)
            {
                mw_printf("Failed to get data for .amdil section: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (verbose)
            {
                mw_printf("Replacing section data of type %d, off %d align "ZU"\n",
                          data->d_type,
                          (int) data->d_off,
                          data->d_align);
            }


            /* Before we overwrite it, there is information we would like to extract */
            uavComment = strstr((const char*) data->d_buf, ";uavid:");
            if (!uavComment || (sscanf(uavComment, ";uavid:%d\n", &uavId) != 1))
            {
                mw_printf("Error reading uavid from IL comment\n");
                uavId = -1;
            }

            ilSrc = getILSrc(nStream, target, uavId, &ilSrcLen);
            if (!ilSrc || (ilSrcLen == 0))
            {
                mw_printf("Failed to get IL source\n");
                return 1;
            }

            data->d_buf = (void*) ilSrc;
            data->d_size = ilSrcLen;

            if (!elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagdata() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (!elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY))
            {
                mw_printf("elf_flagscn() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            /* Don't let libelf rearrange the sections when writing.

               clBuildProgram() crashes on Windows if you don't do
               this with some(?) Catalyst versions
             */
            if (!elf_flagelf(e, ELF_C_SET, ELF_F_LAYOUT))
            {
                mw_printf("elf_flagelf() failed: %s\n", elf_errmsg(-1));
                return 1;
            }

            if (elf_update(e, ELF_C_NULL) < 0)
            {
                mw_printf("elf_update(NULL) failed: %s\n", elf_errmsg(-1));
                return 1;
            }
        }

        if (verboseDebug)
        {
            printf("Section %u %s\n", (unsigned int) elf_ndxscn(scn), name);
        }
    }

    if (elf_update(e, ELF_C_WRITE) < 0)
    {
        mw_printf("elf_update(ELF_C_WRITE) failed: %s\n", elf_errmsg(-1));
        return 1;
    }

    return 0;
}
コード例 #6
0
ファイル: irix-asm-munge.c プロジェクト: Distrotech/cmucl
main(int argc, char **argv)
{
    int fd;
    Elf *elf;
    Elf32_Ehdr *ehdr;
    Elf_Scn *scn;
    Elf_Data *data;
    Elf32_Half ndx;
    Elf32_Shdr *shdr;
    unsigned int *textdata;

    if (argc != 2)
	exit(2);

    assert(!nlist(argv[1], nl));
    assert(nl[0].n_value && !(nl[0].n_value & 0x3));
    assert(nl[1].n_value && !(nl[1].n_value & 0x3));
    assert(nl[2].n_value && !(nl[2].n_value & 0x3));

    if (elf_version(EV_CURRENT) == EV_NONE) {
	fprintf(stderr, "ELF punted! Recompile %s\n", argv[0]);
	exit(1);
    }

    fd = open(argv[1], O_RDWR);
    if (fd < 0) {
	perror("open");
	exit(1);
    }

    elf = elf_begin(fd, ELF_C_RDWR, NULL);

    ehdr = elf32_getehdr(elf);
    assert(ehdr);
    /* want SHT_PROGBITS section named .text */
    ndx = ehdr->e_shstrndx;
    scn = NULL;
    while ((scn = elf_nextscn(elf, scn))) {
	char *name = NULL;

	if ((shdr = elf32_getshdr(scn)))
	    name = elf_strptr(elf, ndx, (size_t) shdr->sh_name);
	if (!strcmp(name, ".text"))
	    break;
    }

    data = elf_getdata(scn, NULL);
    assert(data && data->d_size && !data->d_off);
    textdata = (unsigned int *) data->d_buf;

    /* process */
    assert(textdata[nl[0].n_value / 4] == 0x000B000D);
    textdata[nl[0].n_value / 4] = type_ReturnPcHeader;

    assert(textdata[nl[1].n_value / 4] == 0x000A000D);
    assert(textdata[nl[1].n_value / 4 + 1] == 0x000B000D);
    assert(textdata[nl[1].n_value / 4 + 2] == 0x000B000D);
    textdata[nl[1].n_value / 4 + 1] = 0x0417FECC;
    textdata[nl[1].n_value / 4 + 2] = 0x01000000;

    assert(textdata[nl[2].n_value / 4] == 0x000B000D);
    textdata[nl[2].n_value / 4] = type_ReturnPcHeader;

    elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY);
    elf_update(elf, ELF_C_WRITE);
    elf_end(elf);
}