Fix test for sections with different VMA<->LMA relationships so that it only applies...
[binutils-gdb.git] / gas / codeview.c
blob3eaa7a64fd2dc70c9be983941744a685b788a1d2
1 /* codeview.c - CodeView debug support
2 Copyright (C) 2022-2024 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to the Free
18 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 #include "as.h"
22 #include "codeview.h"
23 #include "subsegs.h"
24 #include "filenames.h"
25 #include "md5.h"
27 #if defined (TE_PE) && defined (O_secrel)
29 #define NUM_MD5_BYTES 16
31 #define FILE_ENTRY_PADDING 2
32 #define FILE_ENTRY_LENGTH (sizeof (struct file_checksum) + NUM_MD5_BYTES \
33 + FILE_ENTRY_PADDING)
35 struct line
37 struct line *next;
38 unsigned int lineno;
39 addressT frag_offset;
42 struct line_file
44 struct line_file *next;
45 unsigned int fileno;
46 struct line *lines_head, *lines_tail;
47 unsigned int num_lines;
50 struct line_block
52 struct line_block *next;
53 segT seg;
54 unsigned int subseg;
55 fragS *frag;
56 symbolS *sym;
57 struct line_file *files_head, *files_tail;
60 struct source_file
62 struct source_file *next;
63 unsigned int num;
64 char *filename;
65 uint32_t string_pos;
66 uint8_t md5[NUM_MD5_BYTES];
69 static struct line_block *blocks_head = NULL, *blocks_tail = NULL;
70 static struct source_file *files_head = NULL, *files_tail = NULL;
71 static unsigned int num_source_files = 0;
73 /* Return the size of the current fragment (taken from dwarf2dbg.c). */
74 static offsetT
75 get_frag_fix (fragS *frag, segT seg)
77 frchainS *fr;
79 if (frag->fr_next)
80 return frag->fr_fix;
82 for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next)
83 if (fr->frch_last == frag)
84 return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal;
86 abort ();
89 /* Emit a .secrel32 relocation. */
90 static void
91 emit_secrel32_reloc (symbolS *sym)
93 expressionS exp;
95 memset (&exp, 0, sizeof (exp));
96 exp.X_op = O_secrel;
97 exp.X_add_symbol = sym;
98 exp.X_add_number = 0;
99 emit_expr (&exp, sizeof (uint32_t));
102 /* Emit a .secidx relocation. */
103 static void
104 emit_secidx_reloc (symbolS *sym)
106 expressionS exp;
108 memset (&exp, 0, sizeof (exp));
109 exp.X_op = O_secidx;
110 exp.X_add_symbol = sym;
111 exp.X_add_number = 0;
112 emit_expr (&exp, sizeof (uint16_t));
115 /* Write the DEBUG_S_STRINGTABLE subsection. */
116 static void
117 write_string_table (void)
119 uint32_t len;
120 unsigned int padding;
121 char *ptr, *start;
123 len = 1;
125 for (struct source_file *sf = files_head; sf; sf = sf->next)
127 len += strlen (sf->filename) + 1;
130 if (len % 4)
131 padding = 4 - (len % 4);
132 else
133 padding = 0;
135 ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len + padding);
137 bfd_putl32 (DEBUG_S_STRINGTABLE, ptr);
138 ptr += sizeof (uint32_t);
139 bfd_putl32 (len, ptr);
140 ptr += sizeof (uint32_t);
142 start = ptr;
144 *ptr = 0;
145 ptr++;
147 for (struct source_file *sf = files_head; sf; sf = sf->next)
149 size_t fn_len = strlen (sf->filename);
151 sf->string_pos = ptr - start;
153 memcpy(ptr, sf->filename, fn_len + 1);
154 ptr += fn_len + 1;
157 memset (ptr, 0, padding);
160 /* Write the DEBUG_S_FILECHKSMS subsection. */
161 static void
162 write_checksums (void)
164 uint32_t len;
165 char *ptr;
167 len = FILE_ENTRY_LENGTH * num_source_files;
169 ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len);
171 bfd_putl32 (DEBUG_S_FILECHKSMS, ptr);
172 ptr += sizeof (uint32_t);
173 bfd_putl32 (len, ptr);
174 ptr += sizeof (uint32_t);
176 for (struct source_file *sf = files_head; sf; sf = sf->next)
178 struct file_checksum fc;
180 fc.file_id = sf->string_pos;
181 fc.checksum_length = NUM_MD5_BYTES;
182 fc.checksum_type = CHKSUM_TYPE_MD5;
184 memcpy (ptr, &fc, sizeof (struct file_checksum));
185 ptr += sizeof (struct file_checksum);
187 memcpy (ptr, sf->md5, NUM_MD5_BYTES);
188 ptr += NUM_MD5_BYTES;
190 memset (ptr, 0, FILE_ENTRY_PADDING);
191 ptr += FILE_ENTRY_PADDING;
195 /* Write the DEBUG_S_LINES subsection. */
196 static void
197 write_lines_info (void)
199 while (blocks_head)
201 struct line_block *lb;
202 struct line_file *lf;
203 uint32_t len;
204 uint32_t off;
205 char *ptr;
207 lb = blocks_head;
209 bfd_putl32 (DEBUG_S_LINES, frag_more (sizeof (uint32_t)));
211 len = sizeof (struct cv_lines_header);
213 for (lf = lb->files_head; lf; lf = lf->next)
215 len += sizeof (struct cv_lines_block);
216 len += sizeof (struct cv_line) * lf->num_lines;
219 bfd_putl32 (len, frag_more (sizeof (uint32_t)));
221 /* Write the header (struct cv_lines_header). We can't use a struct
222 for this as we're also emitting relocations. */
224 emit_secrel32_reloc (lb->sym);
225 emit_secidx_reloc (lb->sym);
227 ptr = frag_more (len - sizeof (uint32_t) - sizeof (uint16_t));
229 /* Flags */
230 bfd_putl16 (0, ptr);
231 ptr += sizeof (uint16_t);
233 off = lb->files_head->lines_head->frag_offset;
235 /* Length of region */
236 bfd_putl32 (get_frag_fix (lb->frag, lb->seg) - off, ptr);
237 ptr += sizeof (uint32_t);
239 while (lb->files_head)
241 struct cv_lines_block *block = (struct cv_lines_block *) ptr;
243 lf = lb->files_head;
245 bfd_putl32(lf->fileno * FILE_ENTRY_LENGTH, &block->file_id);
246 bfd_putl32(lf->num_lines, &block->num_lines);
247 bfd_putl32(sizeof (struct cv_lines_block)
248 + (sizeof (struct cv_line) * lf->num_lines),
249 &block->length);
251 ptr += sizeof (struct cv_lines_block);
253 while (lf->lines_head)
255 struct line *l;
256 struct cv_line *l2 = (struct cv_line *) ptr;
258 l = lf->lines_head;
260 /* Only the bottom 24 bits of line_no actually encode the
261 line number. The top bit is a flag meaning "is
262 a statement". */
264 bfd_putl32 (l->frag_offset - off, &l2->offset);
265 bfd_putl32 (0x80000000 | (l->lineno & 0xffffff),
266 &l2->line_no);
268 lf->lines_head = l->next;
270 free(l);
272 ptr += sizeof (struct cv_line);
275 lb->files_head = lf->next;
276 free (lf);
279 blocks_head = lb->next;
281 free (lb);
285 /* Return the CodeView constant for the selected architecture. */
286 static uint16_t
287 target_processor (void)
289 switch (stdoutput->arch_info->arch)
291 case bfd_arch_i386:
292 if (stdoutput->arch_info->mach & bfd_mach_x86_64)
293 return CV_CFL_X64;
294 else
295 return CV_CFL_80386;
297 case bfd_arch_aarch64:
298 return CV_CFL_ARM64;
300 default:
301 return 0;
305 /* Write the CodeView symbols, describing the object name and
306 assembler version. */
307 static void
308 write_symbols_info (void)
310 static const char assembler[] = "GNU AS " VERSION;
312 char *path = lrealpath (out_file_name);
313 char *path2 = remap_debug_filename (path);
314 size_t path_len, padding;
315 uint32_t len;
316 struct OBJNAMESYM objname;
317 struct COMPILESYM3 compile3;
318 char *ptr;
320 free (path);
321 path = path2;
323 path_len = strlen (path);
325 len = sizeof (struct OBJNAMESYM) + path_len + 1;
326 len += sizeof (struct COMPILESYM3) + sizeof (assembler);
328 if (len % 4)
329 padding = 4 - (len % 4);
330 else
331 padding = 0;
333 len += padding;
335 ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len);
337 bfd_putl32 (DEBUG_S_SYMBOLS, ptr);
338 ptr += sizeof (uint32_t);
339 bfd_putl32 (len, ptr);
340 ptr += sizeof (uint32_t);
342 /* Write S_OBJNAME entry. */
344 bfd_putl16 (sizeof (struct OBJNAMESYM) - sizeof (uint16_t) + path_len + 1,
345 &objname.length);
346 bfd_putl16 (S_OBJNAME, &objname.type);
347 bfd_putl32 (0, &objname.signature);
349 memcpy (ptr, &objname, sizeof (struct OBJNAMESYM));
350 ptr += sizeof (struct OBJNAMESYM);
351 memcpy (ptr, path, path_len + 1);
352 ptr += path_len + 1;
354 free (path);
356 /* Write S_COMPILE3 entry. */
358 bfd_putl16 (sizeof (struct COMPILESYM3) - sizeof (uint16_t)
359 + sizeof (assembler) + padding, &compile3.length);
360 bfd_putl16 (S_COMPILE3, &compile3.type);
361 bfd_putl32 (CV_CFL_MASM, &compile3.flags);
362 bfd_putl16 (target_processor (), &compile3.machine);
363 bfd_putl16 (0, &compile3.frontend_major);
364 bfd_putl16 (0, &compile3.frontend_minor);
365 bfd_putl16 (0, &compile3.frontend_build);
366 bfd_putl16 (0, &compile3.frontend_qfe);
367 bfd_putl16 (0, &compile3.backend_major);
368 bfd_putl16 (0, &compile3.backend_minor);
369 bfd_putl16 (0, &compile3.backend_build);
370 bfd_putl16 (0, &compile3.backend_qfe);
372 memcpy (ptr, &compile3, sizeof (struct COMPILESYM3));
373 ptr += sizeof (struct COMPILESYM3);
374 memcpy (ptr, assembler, sizeof (assembler));
375 ptr += sizeof (assembler);
377 memset (ptr, 0, padding);
380 /* Processing of the file has finished, emit the .debug$S section. */
381 void
382 codeview_finish (void)
384 segT seg;
386 if (!blocks_head)
387 return;
389 seg = subseg_new (".debug$S", 0);
391 bfd_set_section_flags (seg, SEC_READONLY | SEC_NEVER_LOAD);
393 bfd_putl32 (CV_SIGNATURE_C13, frag_more (sizeof (uint32_t)));
395 write_string_table ();
396 write_checksums ();
397 write_lines_info ();
398 write_symbols_info ();
401 /* Assign a new index number for the given file, or return the existing
402 one if already assigned. */
403 static unsigned int
404 get_fileno (const char *file)
406 struct source_file *sf;
407 char *path = lrealpath (file);
408 char *path2 = remap_debug_filename (path);
409 size_t path_len;
410 FILE *f;
412 free (path);
413 path = path2;
415 path_len = strlen (path);
417 for (sf = files_head; sf; sf = sf->next)
419 if (path_len == strlen (sf->filename)
420 && !filename_ncmp (sf->filename, path, path_len))
422 free (path);
423 return sf->num;
427 sf = xmalloc (sizeof (struct source_file));
429 sf->next = NULL;
430 sf->num = num_source_files;
431 sf->filename = path;
433 f = fopen (file, "r");
434 if (!f)
435 as_fatal (_("could not open %s for reading"), file);
437 if (md5_stream (f, sf->md5))
439 fclose(f);
440 as_fatal (_("md5_stream failed"));
443 fclose(f);
445 if (!files_head)
446 files_head = sf;
447 else
448 files_tail->next = sf;
450 files_tail = sf;
452 num_source_files++;
454 return num_source_files - 1;
457 /* Called for each new line in asm file. */
458 void
459 codeview_generate_asm_lineno (void)
461 const char *file;
462 unsigned int filenr;
463 unsigned int lineno;
464 struct line *l;
465 symbolS *sym = NULL;
466 struct line_block *lb;
467 struct line_file *lf;
469 file = as_where (&lineno);
471 filenr = get_fileno (file);
473 if (!blocks_tail || blocks_tail->frag != frag_now)
475 static int label_num = 0;
476 char name[32];
478 sprintf (name, ".Loc.%u", label_num);
479 label_num++;
480 sym = symbol_new (name, now_seg, frag_now, frag_now_fix ());
482 lb = xmalloc (sizeof (struct line_block));
483 lb->next = NULL;
484 lb->seg = now_seg;
485 lb->subseg = now_subseg;
486 lb->frag = frag_now;
487 lb->sym = sym;
488 lb->files_head = lb->files_tail = NULL;
490 if (!blocks_head)
491 blocks_head = lb;
492 else
493 blocks_tail->next = lb;
495 blocks_tail = lb;
497 else
499 lb = blocks_tail;
502 if (!lb->files_tail || lb->files_tail->fileno != filenr)
504 lf = xmalloc (sizeof (struct line_file));
505 lf->next = NULL;
506 lf->fileno = filenr;
507 lf->lines_head = lf->lines_tail = NULL;
508 lf->num_lines = 0;
510 if (!lb->files_head)
511 lb->files_head = lf;
512 else
513 lb->files_tail->next = lf;
515 lb->files_tail = lf;
517 else
519 lf = lb->files_tail;
522 l = xmalloc (sizeof (struct line));
523 l->next = NULL;
524 l->lineno = lineno;
525 l->frag_offset = frag_now_fix ();
527 if (!lf->lines_head)
528 lf->lines_head = l;
529 else
530 lf->lines_tail->next = l;
532 lf->lines_tail = l;
533 lf->num_lines++;
536 #else
538 void
539 codeview_finish (void)
543 void
544 codeview_generate_asm_lineno (void)
548 #endif /* TE_PE && O_secrel */