File: common.h

package info (click to toggle)
pesign 116-8.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,112 kB
  • sloc: ansic: 14,144; sh: 784; makefile: 226
file content (153 lines) | stat: -rw-r--r-- 3,693 bytes parent folder | download
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
// SPDX-License-Identifier: GPLv2
/*
 * common.h - common types and helpers
 * Copyright Peter Jones <pjones@redhat.com>
 * Copyright Red Hat, Inc.
 */
#ifndef LIBDPE_COMMON_H
#define LIBDPE_COMMON_H 1

#include "fix_coverity.h"

#include <stdlib.h>
#include <sys/mman.h>

#define pwrite_retry(fd, buf,  len, off) \
	TEMP_FAILURE_RETRY (pwrite (fd, buf, len, off))
#define write_retry(fd, buf, n) \
	TEMP_FAILURE_RETRY (write (fd, buf, n))
#define pread_retry(fd, buf,  len, off) \
	TEMP_FAILURE_RETRY (pread (fd, buf, len, off))

#define is_64_bit(pe) ((pe)->flags & IMAGE_FILE_32BIT_MACHINE)

#define xfree(x) ({if (x) { free(x); x = NULL; }})
#define xmunmap(addr, size) ({if (addr) { munmap(addr,size); addr = NULL; }})

#include <stdio.h>

static inline void * UNUSED
compute_mem_addr(Pe *pe, off_t offset)
{
	/* XXX this might not work when we're not mmapped */
	return (char *)pe->map_address + le32_to_cpu(offset);
}

static inline uint32_t UNUSED
compute_file_addr(Pe *pe, void *addr)
{
	/* XXX this might not work when we're not mmapped */
	return cpu_to_le32((char *)addr - ((char *)pe->map_address));
}

static inline size_t UNUSED
get_shnum(void *map_address, size_t maxsize UNUSED)
{
	size_t result = 0;
	void *buf = (void *)map_address;
	struct mz_hdr *mz = (struct mz_hdr *)buf;

	if (mz == NULL)
		return (size_t)-1l;

	off_t hdr = (off_t)le32_to_cpu(mz->peaddr);
	struct pe_hdr *pe = (struct pe_hdr *)(buf + hdr);

	uint16_t sections = pe->sections;

	result = le16_to_cpu(sections);

	return result;
}

static inline Pe_Kind UNUSED
determine_kind(void *buf, size_t len UNUSED)
{
	Pe_Kind retval = PE_K_NONE;
	uint16_t mz_magic = MZ_MAGIC;
	struct mz_hdr *mz = (struct mz_hdr *)buf;

	if (cmp_le16(&mz->magic, &mz_magic))
		return retval;

	retval = PE_K_MZ;

	off_t hdr = (off_t)le32_to_cpu(mz->peaddr);
	struct pe_hdr *pe = (struct pe_hdr *)(buf + hdr);
	uint32_t pe_magic = PE_MAGIC;

	if (cmp_le32(&pe->magic, &pe_magic))
		return retval;

	if (pe->flags & IMAGE_FILE_EXECUTABLE_IMAGE) {
		if (le32_to_cpu(pe->opt_hdr_size) == 0) {
			/* this PE header is invalid, so return PE_K_MZ */
			return retval;
		}

		struct pe32_opt_hdr *peo =
			(struct pe32_opt_hdr *)(buf + hdr + sizeof(*pe));

		/* if we don't have an optional header, fall back to testing
		 * our machine type list... */
		switch (le16_to_cpu(peo->magic)) {
			case PE_OPT_MAGIC_PE32:
				retval = PE_K_PE_EXE;
				break;
			case PE_OPT_MAGIC_PE32_ROM:
				retval = PE_K_PE_ROM;
				break;
			case PE_OPT_MAGIC_PE32PLUS:
				retval = PE_K_PE64_EXE;
				break;
			default:
				/* some magic we don't know?  Guess based on
				 * machine type */
				retval = is_64_bit(pe)
					? PE_K_PE64_EXE : PE_K_PE_EXE;
				break;
		}
	} else {
		/* this is an object file */
		retval = is_64_bit(pe) ? PE_K_PE64_OBJ : PE_K_PE_OBJ;
	}

	return retval;
}

#undef choose_kind
#undef is_64_bit

static inline Pe * UNUSED
allocate_pe(int fildes, void *map_address, size_t maxsize,
	Pe_Cmd cmd, Pe *parent, Pe_Kind kind, size_t extra)
{
	Pe *result = (Pe *) calloc(1, sizeof (Pe) + extra);
	if (result == NULL) {
		__libpe_seterrno(PE_E_NOMEM);
	} else {
		result->kind = kind;
		result->ref_count = 1;
		result->cmd = cmd;
		result->fildes = fildes;
		result->maximum_size = maxsize;
		result->map_address = map_address;
		result->parent = parent;
	}

	return result;
}

/* We often have to update a flag iff a value changed.  Make this
 * convenient.  */
#define update_if_changed(var, exp, flag)				\
	({								\
		__typeof__ (var) *_var = &(var);			\
		__typeof__ (exp) _exp = (exp);				\
		if (*_var != _exp) {					\
			*_var = _exp;					\
			(flag) |= PE_F_DIRTY;				\
		}							\
	})

#endif /* LIBDPE_COMMON_H */