summaryrefslogtreecommitdiffhomepage
path: root/src/reader/pe_read_coff_symbol.c
blob: eefb87acb5586d8f2e93b909040dae643da517e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/***************************************************************/
/*  perk: PE Resource Kit                                      */
/*  Copyright (C) 2015--2021  Z. Gilboa                        */
/*  Released under GPLv2 and GPLv3; see COPYING.PERK.          */
/***************************************************************/

#include <string.h>

#include <perk/perk.h>
#include <perk/perk_consts.h>
#include <perk/perk_structs.h>
#include "perk_endian_impl.h"
#include "perk_reader_impl.h"

int pe_read_coff_symbol(
	const struct pe_raw_coff_symbol *	p,
	struct pe_meta_coff_symbol *		m,
	const struct pe_meta_coff_file_hdr *	coff,
	void *					base)
{
	uint32_t	roffset;
	char *		mark;
	unsigned	bias = 0;

	m->cs_long_name           = 0;
	m->cs_value               = pe_read_long(p->cs_value);
	m->cs_section_number      = pe_read_short(p->cs_section_number);
	m->cs_type                = pe_read_short(p->cs_type);
	m->cs_storage_class       = p->cs_storage_class[0];
	m->cs_num_of_aux_symbols  = p->cs_num_of_aux_symbols[0];

	memset(m->cs_name,0,sizeof(m->cs_name));

	if (p->cs_storage_class[0] == PE_IMAGE_SYM_CLASS_FILE)
		if (p->cs_num_of_aux_symbols[0])
			if (!p[1].cs_value[0])
				bias = 1;

	p += bias;

	if (!bias && (p->cs_storage_class[0] == PE_IMAGE_SYM_CLASS_FILE)
			&& p->cs_num_of_aux_symbols[0]) {
		memcpy(m->cs_name,p[1].cs_name,sizeof(*p));

	} else if (p->cs_name[0]) {
		memcpy(m->cs_name,p->cs_name,sizeof(p->cs_name));

	} else if (!p->cs_name[1] && !p->cs_name[2] && !p->cs_name[3]) {
		mark	= (char *)base;
		roffset	= pe_read_long(&p->cs_name[4]);

		if (roffset < coff->cfh_size_of_str_tbl)
			m->cs_long_name = mark + coff->cfh_ptr_to_str_tbl + roffset;
	}

	return 0;
}