Example #1
0
/*
 * Read attribute set from memory buffer (see header file for more information).
 */
Pmelf_attribute_set *
pmelf_read_attribute_set(const uint8_t *b, unsigned bsize, int needswap, const char *obj_name)
{
Pmelf_attribute_set    *rval = 0;
Pmelf_attribute_vendor *pv;
Pmelf_Off              n,nbeg;
int                    l;
uint8_t                v;
const char             *vendor_name;
Pmelf_attribute_tbl    *patbl;
Elf32_Word             len,tag,sublen;

	if ( ! known_vendors ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): no vendors registered\n");
		/* No vendors registered; save us the trouble */
		return 0;
	}

	if ( ! (rval = calloc(sizeof(*rval),1)) ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): no memory\n");
		return 0;
	}

	if ( ! (rval->obj_name = strdup(obj_name)) ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): no memory (for obj_name)\n");
		goto cleanup;
	}

	n = 0;

	while ( n < bsize ) {
		nbeg = n;

		if ( FORMAT_VERSION_A != (v = b[n++]) ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): unknown attribute format version %i\n", v);
			goto cleanup;
		}

		if ( pmelf_getword(needswap, b+n, bsize-n, &len, "subsection") )
			goto cleanup;

		n += sizeof(len);
			
		if ( nbeg + len + 1 > bsize ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): vendor subsection length > section length\n");
			goto cleanup;
		}

		for ( l = n; b[l]; ) {
			if ( ++l >= bsize ) {
				PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): reading beyond section (getting vendor name)\n");
				goto cleanup;
			}
		}

		vendor_name = (const char*)(b + n);

		n = l+1;

		if ( (l = pmelf_guleb128(b+n, &tag, bsize - n)) < 0 ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_size() reading beyond subsubsection (getting tag)\n");
			goto cleanup;
		}

		n += l;

		if ( pmelf_getword(needswap, b + n, bsize - n, &sublen, "subsubsection") )
			goto cleanup;

		n += sizeof(sublen);

		/* subsubsection length includes byte count for tag and length itself */
		sublen -= sizeof(sublen) + l;

		switch ( tag ) {
			case Tag_File:
				for ( pv = known_vendors; pv && strcmp(pv->name, vendor_name); )
					pv = pv->next;

				if ( !pv ) {
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): no handlers for vendor '%s' found\n", vendor_name);
					goto cleanup;
				}

				for ( patbl=0, l=0; l<ATTR_MAX_VENDORS; l++ ) {
					if ( ! rval->attributes[l].file_attributes
						|| rval->attributes[l].file_attributes->pv == pv ) {
						/* setting a covers the case where we use a new empty slot */
						patbl = rval->attributes[l].file_attributes;
						break;
					}
				}

				if ( ! patbl ) {
					if ( l >= ATTR_MAX_VENDORS ) {
						PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): not enough vendor slots\n");
						goto cleanup;
					}

					/* create attribute table */
					if ( !(patbl = calloc(sizeof(*patbl) + sizeof(patbl->map[0])*(pv->max_tag+1), 1)) ) {
						PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): no memory\n");
						goto cleanup;
					}

					patbl->vals  = 0;
					patbl->avail = 0;
					patbl->idx   = 1;	/* first entry is empty/unused */
					patbl->pv    = pv;
					patbl->aset  = rval;

					rval->attributes[l].file_attributes = patbl;
				}

				/* read attributes into table */
				if ( pv->file_attributes_read(patbl, b+n, sublen) )
					goto cleanup;
			break;

			case Tag_Section:
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): Tag_Section no yet supported\n");
					goto cleanup;
			case Tag_Symbol:
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): Tag_Symbol no yet supported\n");
					goto cleanup;
			default:
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_read_attribute_set(): unsupported tag %"PRIi32"\n", tag);
					goto cleanup;
		}

		n = nbeg + len + 1;
	}

	return rval;

cleanup:
	pmelf_destroy_attribute_set(rval);
	return 0;
}
Example #2
0
/*
 * Decode attributes from byte stream in memory (public format; see header for
 * more detailed description.
 */
int
pmelf_pub_file_attributes_read(Pmelf_attribute_tbl *patbl, const uint8_t *buf, unsigned size)
{
Elf32_Word            tag;
int                   l,n;
Pmelf_pub_attribute_t tagt;
Elf32_Word            ival;
const char *          sval;
Pmelf_attribute_list  *el,**pn,**pp;
unsigned              csz;

	if ( !size )
		return 0;

	if ( ! patbl ) {
		PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read(): no attribute table (internal error)\n");
		return -1;
	}

	while ( size ) {

		if ( (n = pmelf_guleb128(buf, &tag, size)) < 0 ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() reading beyond subsubsection (getting tag)\n");
			goto cleanup;
		}
		buf  += n;
		size -= n;

		if ( patbl->avail == 0 && (tag <= patbl->pv->max_tag && Tag_Compat != tag) ) {

			csz = CHUNKSZ < patbl->pv->max_tag ? CHUNKSZ : patbl->pv->max_tag;

			if ( !(patbl->vals = realloc(patbl->vals, sizeof(*patbl->vals)*(patbl->idx + csz))) ) {
				PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read(): no memory\n");
				goto cleanup;
			}

			patbl->avail  += csz;
		}

		ival = 0;
		sval = 0;

		/* FIXME: we cannot have multiple identical tags in the array (but could in the linked list part) */
		if ( (tag <= patbl->pv->max_tag && Tag_Compat != tag) && patbl->map[tag] ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() tag %"PRIi32" already defined\n", tag);
			goto cleanup;
		}

		if ( Tag_Compat == tag ) {
			tagt = Pmelf_Attribute_Type_both;
		} else if ( ! patbl->pv->file_attributes_tag_type ) {
			PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() vendor %s has no type handler!\n", patbl->pv->name );
			tagt = Pmelf_Attribute_Type_unknown;
		} else {
			tagt = patbl->pv->file_attributes_tag_type(patbl, tag);
		}

		switch ( tagt ) {
			default:
				PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() unknown tag %"PRIi32"\n", tag );
				goto cleanup;
			case Pmelf_Attribute_Type_none:
				continue;

			case Pmelf_Attribute_Type_num:
			case Pmelf_Attribute_Type_both:
				if ( (n = pmelf_guleb128(buf, &ival, size)) < 0 ) {
					PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() reading beyond subsubsection (getting (i)value)\n");
					goto cleanup;
				}
				buf  += n;
				size -= n;
				if ( Pmelf_Attribute_Type_num == tagt )
					break;
				/* else fall thru */

			case Pmelf_Attribute_Type_str:
				for ( l=0; buf[l++]; ) {
					if ( l >= size ) {
						PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() reading beyond subsubsection (getting (s)value)\n");
						goto cleanup;
					}
				}
				sval  = (const char*)buf;
				buf  += l;
				size -= l;
			break;
		}

		/* Tag_Compat always go to the list */
		if ( tag > patbl->pv->max_tag || Tag_Compat == tag ) {
			if ( ! (el = calloc( sizeof(*el), 1 ) ) ) {
				PMELF_PRINTF( pmelf_err, PMELF_PRE"pmelf_pub_file_attributes_read() no memory for attribute list element\n");
				goto cleanup;
			}
			/* append to possibly existing instances of 'tag' */
			for ( pp = &patbl->lst; *pp; pp = &(*pp)->next ) {
				if ( (*pp)->att.tag == tag ) {
					for ( pn = &(*pp)->next; *pn && (*pn)->att.tag == tag; pp = pn)
						;
					break;
				}
			}
			el->next          = *pp;
			*pp               = el;
			el->att.tag       = tag;
			el->att.val.pub.i = ival;
			el->att.val.pub.s = sval;
		} else {
			patbl->map[tag]               = patbl->idx;
			patbl->vals[patbl->idx].pub.i = ival;
			patbl->vals[patbl->idx].pub.s = sval;
			patbl->idx++;
		}
	}

	return 0;

cleanup:
	return -1;
}