UFO: Alien Invasion
Loading...
Searching...
No Matches
bfd.cpp
Go to the documentation of this file.
1
5
6/*
7All original material Copyright (C) 2002-2025 UFO: Alien Invasion.
8
9Copyright (C) 1997-2001 Id Software, Inc.
10
11This program is free software; you can redistribute it and/or
12modify it under the terms of the GNU General Public License
13as published by the Free Software Foundation; either version 2
14of the License, or (at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19
20See the GNU General Public License for more details.
21
22You should have received a copy of the GNU General Public License
23along with this program; if not, write to the Free Software
24Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
26*/
27
28#include "../common/common.h"
29
30#ifdef HAVE_BFD_H
31#include "bfd.h"
32
33/* binutils-libs 2.34 compatibility */
34#ifndef bfd_get_section_flags
35# define bfd_get_section_flags(bfd, section) (bfd_section_flags(section))
36#endif
37
38#ifndef bfd_get_section_vma
39# define bfd_get_section_vma(bfd, section) (bfd_section_vma(section))
40#endif
41
42#ifndef bfd_get_section_size
43# define bfd_get_section_size(section) (bfd_section_size(section))
44#endif
45
46void output_init (struct output_buffer* ob, char* buf, size_t sz)
47{
48 ob->buf = buf;
49 ob->sz = sz;
50 ob->ptr = 0;
51 ob->buf[0] = '\0';
52}
53
54void output_print (struct output_buffer* ob, const char* format, ...)
55{
56 va_list ap;
57 if (ob->sz == ob->ptr)
58 return;
59 ob->buf[ob->ptr] = '\0';
60 va_start(ap, format);
61 vsnprintf(ob->buf + ob->ptr, ob->sz - ob->ptr, format, ap);
62 va_end(ap);
63
64 ob->ptr = strlen(ob->buf + ob->ptr) + ob->ptr;
65}
66
67static void lookup_section (bfd* abfd, asection* sec, void* opaque_data)
68{
69 struct find_info* data = (struct find_info*)opaque_data;
70
71 if (data->func)
72 return;
73
74 if (!(bfd_get_section_flags(abfd, sec) & SEC_ALLOC))
75 return;
76
77 const bfd_vma vma = bfd_get_section_vma(abfd, sec);
78 if (data->counter < vma || vma + bfd_get_section_size(sec) <= data->counter)
79 return;
80
81 bfd_find_nearest_line(abfd, sec, data->symbol, data->counter - vma,
82 &(data->file), &(data->func), &(data->line));
83}
84
85void find (struct bfd_ctx * b, size_t offset, const char** file, const char** func, unsigned* line)
86{
87 struct find_info data;
88 data.func = nullptr;
89 data.symbol = b->symbol;
90 data.counter = offset;
91 data.file = nullptr;
92 data.func = nullptr;
93 data.line = 0;
94
95 bfd_map_over_sections(b->handle, &lookup_section, &data);
96 if (file) {
97 *file = data.file;
98 }
99 if (func) {
100 *func = data.func;
101 }
102 if (line) {
103 *line = data.line;
104 }
105}
106
107static void list_matching_formats (struct output_buffer* ob, const char* procname, char** p)
108{
109 if (!p || !*p)
110 return;
111
112 output_print(ob, "%s: Matching formats: ", procname);
113 while (*p)
114 output_print(ob, " %s", *p++);
115 output_print(ob, "\n");
116}
117
118static int init_bfd_ctx (struct bfd_ctx* bc, const char* procname, struct output_buffer* ob)
119{
120 void* symbol_table;
121 unsigned dummy = 0;
122 char** matching = nullptr;
123
124 bc->handle = nullptr;
125 bc->symbol = nullptr;
126
127 bfd* b = bfd_openr(procname, 0);
128 if (!b) {
129 output_print(ob, "Failed to open bfd from (%s)\n", procname);
130 return 1;
131 }
132
133 if (bfd_check_format(b, bfd_archive)) {
134 output_print(ob, "Cannot get addresses from archive (%s)\n", b->filename);
135 bfd_close(b);
136 return -1;
137 }
138
139 if (!bfd_check_format_matches(b, bfd_object, &matching)) {
140 const char* errmsg = bfd_errmsg(bfd_get_error());
141 output_print(ob, "%s (%s)\n", errmsg, b->filename);
142 if (bfd_get_error() == bfd_error_file_ambiguously_recognized) {
143 list_matching_formats(ob, b->filename, matching);
144 free(matching);
145 }
146 bfd_close(b);
147 return -1;
148 }
149
150 if ((bfd_get_file_flags(b) & HAS_SYMS) == 0) {
151 const char* errmsg = bfd_errmsg(bfd_get_error());
152 output_print(ob, "Failed to get file flags from (%s) %s\n", b->filename, errmsg);
153 bfd_close(b);
154 return 1;
155 }
156
157 if (bfd_read_minisymbols(b, FALSE, &symbol_table, &dummy) == 0) {
158 if (bfd_read_minisymbols(b, TRUE, &symbol_table, &dummy) < 0) {
159 const char* errmsg = bfd_errmsg(bfd_get_error());
160 output_print(ob, "Failed to read symbols from (%s): %s\n", b->filename, errmsg);
161 free(symbol_table);
162 bfd_close(b);
163 return 1;
164 }
165 }
166
167 bc->handle = b;
168 bc->symbol = (asymbol**)symbol_table;
169
170 return 0;
171}
172
173static void close_bfd_ctx (struct bfd_ctx* bc)
174{
175 free(bc->symbol);
176 if (bc->handle) {
177 bfd_close(bc->handle);
178 }
179}
180
181struct bfd_ctx* get_bc (struct output_buffer* ob, struct bfd_set* set, const char* procname)
182{
183 struct bfd_ctx bc;
184
185 while (set->name) {
186 if (Q_streq(set->name, procname)) {
187 return set->bc;
188 }
189 set = set->next;
190 }
191 if (init_bfd_ctx(&bc, procname, ob)) {
192 return nullptr;
193 }
194 set->next = (bfd_set*)calloc(1, sizeof(*set));
195 set->bc = (bfd_ctx*)malloc(sizeof(struct bfd_ctx));
196 memcpy(set->bc, &bc, sizeof(bc));
197 set->name = strdup(procname);
198
199 return set->bc;
200}
201
202void release_set (struct bfd_set* set)
203{
204 while (set->next) {
205 struct bfd_set* temp = set->next;
206 free(set->name);
207 close_bfd_ctx(set->bc);
208 free(set);
209 set = temp;
210 }
211}
212
213#endif
void list_matching_formats(char **p)
definitions common between client and server, but not game lib
voidpf void * buf
Definition ioapi.h:42
voidpf uLong offset
Definition ioapi.h:45
void format(__printf__, 1, 2)))
QGL_EXTERN GLsizei const GLvoid * data
Definition r_gl.h:89
#define Q_streq(a, b)
Definition shared.h:136