Home | History | Annotate | Line # | Download | only in gas
      1      1.1  christos /* codeview.c - CodeView debug support
      2  1.1.1.2  christos    Copyright (C) 2022-2025 Free Software Foundation, Inc.
      3      1.1  christos 
      4      1.1  christos    This file is part of GAS, the GNU Assembler.
      5      1.1  christos 
      6      1.1  christos    GAS is free software; you can redistribute it and/or modify
      7      1.1  christos    it under the terms of the GNU General Public License as published by
      8      1.1  christos    the Free Software Foundation; either version 3, or (at your option)
      9      1.1  christos    any later version.
     10      1.1  christos 
     11      1.1  christos    GAS is distributed in the hope that it will be useful,
     12      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14      1.1  christos    GNU General Public License for more details.
     15      1.1  christos 
     16      1.1  christos    You should have received a copy of the GNU General Public License
     17      1.1  christos    along with GAS; see the file COPYING.  If not, write to the Free
     18      1.1  christos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19      1.1  christos    02110-1301, USA.  */
     20      1.1  christos 
     21      1.1  christos #include "as.h"
     22      1.1  christos #include "codeview.h"
     23      1.1  christos #include "subsegs.h"
     24      1.1  christos #include "filenames.h"
     25      1.1  christos #include "md5.h"
     26      1.1  christos 
     27      1.1  christos #if defined (TE_PE) && defined (O_secrel)
     28      1.1  christos 
     29      1.1  christos #define NUM_MD5_BYTES       	16
     30      1.1  christos 
     31      1.1  christos #define FILE_ENTRY_PADDING	2
     32      1.1  christos #define FILE_ENTRY_LENGTH	(sizeof (struct file_checksum) + NUM_MD5_BYTES \
     33      1.1  christos 				 + FILE_ENTRY_PADDING)
     34      1.1  christos 
     35      1.1  christos struct line
     36      1.1  christos {
     37      1.1  christos   struct line *next;
     38      1.1  christos   unsigned int lineno;
     39      1.1  christos   addressT frag_offset;
     40      1.1  christos };
     41      1.1  christos 
     42      1.1  christos struct line_file
     43      1.1  christos {
     44      1.1  christos   struct line_file *next;
     45      1.1  christos   unsigned int fileno;
     46      1.1  christos   struct line *lines_head, *lines_tail;
     47      1.1  christos   unsigned int num_lines;
     48      1.1  christos };
     49      1.1  christos 
     50      1.1  christos struct line_block
     51      1.1  christos {
     52      1.1  christos   struct line_block *next;
     53      1.1  christos   segT seg;
     54      1.1  christos   unsigned int subseg;
     55      1.1  christos   fragS *frag;
     56      1.1  christos   symbolS *sym;
     57      1.1  christos   struct line_file *files_head, *files_tail;
     58      1.1  christos };
     59      1.1  christos 
     60      1.1  christos struct source_file
     61      1.1  christos {
     62      1.1  christos   struct source_file *next;
     63      1.1  christos   unsigned int num;
     64      1.1  christos   char *filename;
     65      1.1  christos   uint32_t string_pos;
     66      1.1  christos   uint8_t md5[NUM_MD5_BYTES];
     67      1.1  christos };
     68      1.1  christos 
     69      1.1  christos static struct line_block *blocks_head = NULL, *blocks_tail = NULL;
     70      1.1  christos static struct source_file *files_head = NULL, *files_tail = NULL;
     71      1.1  christos static unsigned int num_source_files = 0;
     72      1.1  christos 
     73      1.1  christos /* Return the size of the current fragment (taken from dwarf2dbg.c).  */
     74      1.1  christos static offsetT
     75      1.1  christos get_frag_fix (fragS *frag, segT seg)
     76      1.1  christos {
     77      1.1  christos   frchainS *fr;
     78      1.1  christos 
     79      1.1  christos   if (frag->fr_next)
     80      1.1  christos     return frag->fr_fix;
     81      1.1  christos 
     82      1.1  christos   for (fr = seg_info (seg)->frchainP; fr; fr = fr->frch_next)
     83      1.1  christos     if (fr->frch_last == frag)
     84      1.1  christos       return (char *) obstack_next_free (&fr->frch_obstack) - frag->fr_literal;
     85      1.1  christos 
     86      1.1  christos   abort ();
     87      1.1  christos }
     88      1.1  christos 
     89      1.1  christos /* Emit a .secrel32 relocation.  */
     90      1.1  christos static void
     91      1.1  christos emit_secrel32_reloc (symbolS *sym)
     92      1.1  christos {
     93      1.1  christos   expressionS exp;
     94      1.1  christos 
     95      1.1  christos   memset (&exp, 0, sizeof (exp));
     96      1.1  christos   exp.X_op = O_secrel;
     97      1.1  christos   exp.X_add_symbol = sym;
     98      1.1  christos   exp.X_add_number = 0;
     99      1.1  christos   emit_expr (&exp, sizeof (uint32_t));
    100      1.1  christos }
    101      1.1  christos 
    102      1.1  christos /* Emit a .secidx relocation.  */
    103      1.1  christos static void
    104      1.1  christos emit_secidx_reloc (symbolS *sym)
    105      1.1  christos {
    106      1.1  christos   expressionS exp;
    107      1.1  christos 
    108      1.1  christos   memset (&exp, 0, sizeof (exp));
    109      1.1  christos   exp.X_op = O_secidx;
    110      1.1  christos   exp.X_add_symbol = sym;
    111      1.1  christos   exp.X_add_number = 0;
    112      1.1  christos   emit_expr (&exp, sizeof (uint16_t));
    113      1.1  christos }
    114      1.1  christos 
    115      1.1  christos /* Write the DEBUG_S_STRINGTABLE subsection.  */
    116      1.1  christos static void
    117      1.1  christos write_string_table (void)
    118      1.1  christos {
    119      1.1  christos   uint32_t len;
    120      1.1  christos   unsigned int padding;
    121      1.1  christos   char *ptr, *start;
    122      1.1  christos 
    123      1.1  christos   len = 1;
    124      1.1  christos 
    125      1.1  christos   for (struct source_file *sf = files_head; sf; sf = sf->next)
    126      1.1  christos     {
    127      1.1  christos       len += strlen (sf->filename) + 1;
    128      1.1  christos     }
    129      1.1  christos 
    130      1.1  christos   if (len % 4)
    131      1.1  christos     padding = 4 - (len % 4);
    132      1.1  christos   else
    133      1.1  christos     padding = 0;
    134      1.1  christos 
    135      1.1  christos   ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len + padding);
    136      1.1  christos 
    137      1.1  christos   bfd_putl32 (DEBUG_S_STRINGTABLE, ptr);
    138      1.1  christos   ptr += sizeof (uint32_t);
    139      1.1  christos   bfd_putl32 (len, ptr);
    140      1.1  christos   ptr += sizeof (uint32_t);
    141      1.1  christos 
    142      1.1  christos   start = ptr;
    143      1.1  christos 
    144      1.1  christos   *ptr = 0;
    145      1.1  christos   ptr++;
    146      1.1  christos 
    147      1.1  christos   for (struct source_file *sf = files_head; sf; sf = sf->next)
    148      1.1  christos     {
    149      1.1  christos       size_t fn_len = strlen (sf->filename);
    150      1.1  christos 
    151      1.1  christos       sf->string_pos = ptr - start;
    152      1.1  christos 
    153      1.1  christos       memcpy(ptr, sf->filename, fn_len + 1);
    154      1.1  christos       ptr += fn_len + 1;
    155      1.1  christos     }
    156      1.1  christos 
    157      1.1  christos   memset (ptr, 0, padding);
    158      1.1  christos }
    159      1.1  christos 
    160      1.1  christos /* Write the DEBUG_S_FILECHKSMS subsection.  */
    161      1.1  christos static void
    162      1.1  christos write_checksums (void)
    163      1.1  christos {
    164      1.1  christos   uint32_t len;
    165      1.1  christos   char *ptr;
    166      1.1  christos 
    167      1.1  christos   len = FILE_ENTRY_LENGTH * num_source_files;
    168      1.1  christos 
    169      1.1  christos   ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len);
    170      1.1  christos 
    171      1.1  christos   bfd_putl32 (DEBUG_S_FILECHKSMS, ptr);
    172      1.1  christos   ptr += sizeof (uint32_t);
    173      1.1  christos   bfd_putl32 (len, ptr);
    174      1.1  christos   ptr += sizeof (uint32_t);
    175      1.1  christos 
    176      1.1  christos   for (struct source_file *sf = files_head; sf; sf = sf->next)
    177      1.1  christos     {
    178      1.1  christos       struct file_checksum fc;
    179      1.1  christos 
    180      1.1  christos       fc.file_id = sf->string_pos;
    181      1.1  christos       fc.checksum_length = NUM_MD5_BYTES;
    182      1.1  christos       fc.checksum_type = CHKSUM_TYPE_MD5;
    183      1.1  christos 
    184      1.1  christos       memcpy (ptr, &fc, sizeof (struct file_checksum));
    185      1.1  christos       ptr += sizeof (struct file_checksum);
    186      1.1  christos 
    187      1.1  christos       memcpy (ptr, sf->md5, NUM_MD5_BYTES);
    188      1.1  christos       ptr += NUM_MD5_BYTES;
    189      1.1  christos 
    190      1.1  christos       memset (ptr, 0, FILE_ENTRY_PADDING);
    191      1.1  christos       ptr += FILE_ENTRY_PADDING;
    192      1.1  christos     }
    193      1.1  christos }
    194      1.1  christos 
    195      1.1  christos /* Write the DEBUG_S_LINES subsection.  */
    196      1.1  christos static void
    197      1.1  christos write_lines_info (void)
    198      1.1  christos {
    199      1.1  christos   while (blocks_head)
    200      1.1  christos     {
    201      1.1  christos       struct line_block *lb;
    202      1.1  christos       struct line_file *lf;
    203      1.1  christos       uint32_t len;
    204      1.1  christos       uint32_t off;
    205      1.1  christos       char *ptr;
    206      1.1  christos 
    207      1.1  christos       lb = blocks_head;
    208      1.1  christos 
    209      1.1  christos       bfd_putl32 (DEBUG_S_LINES, frag_more (sizeof (uint32_t)));
    210      1.1  christos 
    211      1.1  christos       len = sizeof (struct cv_lines_header);
    212      1.1  christos 
    213      1.1  christos       for (lf = lb->files_head; lf; lf = lf->next)
    214      1.1  christos 	{
    215      1.1  christos 	  len += sizeof (struct cv_lines_block);
    216      1.1  christos 	  len += sizeof (struct cv_line) * lf->num_lines;
    217      1.1  christos 	}
    218      1.1  christos 
    219      1.1  christos       bfd_putl32 (len, frag_more (sizeof (uint32_t)));
    220      1.1  christos 
    221      1.1  christos       /* Write the header (struct cv_lines_header).  We can't use a struct
    222      1.1  christos 	 for this as we're also emitting relocations.  */
    223      1.1  christos 
    224      1.1  christos       emit_secrel32_reloc (lb->sym);
    225      1.1  christos       emit_secidx_reloc (lb->sym);
    226      1.1  christos 
    227      1.1  christos       ptr = frag_more (len - sizeof (uint32_t) - sizeof (uint16_t));
    228      1.1  christos 
    229      1.1  christos       /* Flags */
    230      1.1  christos       bfd_putl16 (0, ptr);
    231      1.1  christos       ptr += sizeof (uint16_t);
    232      1.1  christos 
    233      1.1  christos       off = lb->files_head->lines_head->frag_offset;
    234      1.1  christos 
    235      1.1  christos       /* Length of region */
    236      1.1  christos       bfd_putl32 (get_frag_fix (lb->frag, lb->seg) - off, ptr);
    237      1.1  christos       ptr += sizeof (uint32_t);
    238      1.1  christos 
    239      1.1  christos       while (lb->files_head)
    240      1.1  christos 	{
    241      1.1  christos 	  struct cv_lines_block *block = (struct cv_lines_block *) ptr;
    242      1.1  christos 
    243      1.1  christos 	  lf = lb->files_head;
    244      1.1  christos 
    245      1.1  christos 	  bfd_putl32(lf->fileno * FILE_ENTRY_LENGTH, &block->file_id);
    246      1.1  christos 	  bfd_putl32(lf->num_lines, &block->num_lines);
    247      1.1  christos 	  bfd_putl32(sizeof (struct cv_lines_block)
    248      1.1  christos 		     + (sizeof (struct cv_line) * lf->num_lines),
    249      1.1  christos 		     &block->length);
    250      1.1  christos 
    251      1.1  christos 	  ptr += sizeof (struct cv_lines_block);
    252      1.1  christos 
    253      1.1  christos 	  while (lf->lines_head)
    254      1.1  christos 	    {
    255      1.1  christos 	      struct line *l;
    256      1.1  christos 	      struct cv_line *l2 = (struct cv_line *) ptr;
    257      1.1  christos 
    258      1.1  christos 	      l = lf->lines_head;
    259      1.1  christos 
    260      1.1  christos 	      /* Only the bottom 24 bits of line_no actually encode the
    261      1.1  christos 		 line number.  The top bit is a flag meaning "is
    262      1.1  christos 		 a statement".  */
    263      1.1  christos 
    264      1.1  christos 	      bfd_putl32 (l->frag_offset - off, &l2->offset);
    265      1.1  christos 	      bfd_putl32 (0x80000000 | (l->lineno & 0xffffff),
    266      1.1  christos 			  &l2->line_no);
    267      1.1  christos 
    268      1.1  christos 	      lf->lines_head = l->next;
    269      1.1  christos 
    270      1.1  christos 	      free(l);
    271      1.1  christos 
    272      1.1  christos 	      ptr += sizeof (struct cv_line);
    273      1.1  christos 	    }
    274      1.1  christos 
    275      1.1  christos 	  lb->files_head = lf->next;
    276      1.1  christos 	  free (lf);
    277      1.1  christos 	}
    278      1.1  christos 
    279      1.1  christos       blocks_head = lb->next;
    280      1.1  christos 
    281      1.1  christos       free (lb);
    282      1.1  christos     }
    283      1.1  christos }
    284      1.1  christos 
    285      1.1  christos /* Return the CodeView constant for the selected architecture.  */
    286      1.1  christos static uint16_t
    287      1.1  christos target_processor (void)
    288      1.1  christos {
    289      1.1  christos   switch (stdoutput->arch_info->arch)
    290      1.1  christos     {
    291      1.1  christos     case bfd_arch_i386:
    292      1.1  christos       if (stdoutput->arch_info->mach & bfd_mach_x86_64)
    293      1.1  christos 	return CV_CFL_X64;
    294      1.1  christos       else
    295      1.1  christos 	return CV_CFL_80386;
    296      1.1  christos 
    297      1.1  christos     case bfd_arch_aarch64:
    298      1.1  christos       return CV_CFL_ARM64;
    299      1.1  christos 
    300      1.1  christos     default:
    301      1.1  christos       return 0;
    302      1.1  christos     }
    303      1.1  christos }
    304      1.1  christos 
    305      1.1  christos /* Write the CodeView symbols, describing the object name and
    306      1.1  christos    assembler version.  */
    307      1.1  christos static void
    308      1.1  christos write_symbols_info (void)
    309      1.1  christos {
    310      1.1  christos   static const char assembler[] = "GNU AS " VERSION;
    311      1.1  christos 
    312      1.1  christos   char *path = lrealpath (out_file_name);
    313      1.1  christos   char *path2 = remap_debug_filename (path);
    314      1.1  christos   size_t path_len, padding;
    315      1.1  christos   uint32_t len;
    316      1.1  christos   struct OBJNAMESYM objname;
    317      1.1  christos   struct COMPILESYM3 compile3;
    318      1.1  christos   char *ptr;
    319      1.1  christos 
    320      1.1  christos   free (path);
    321      1.1  christos   path = path2;
    322      1.1  christos 
    323      1.1  christos   path_len = strlen (path);
    324      1.1  christos 
    325      1.1  christos   len = sizeof (struct OBJNAMESYM) + path_len + 1;
    326      1.1  christos   len += sizeof (struct COMPILESYM3) + sizeof (assembler);
    327      1.1  christos 
    328      1.1  christos   if (len % 4)
    329      1.1  christos     padding = 4 - (len % 4);
    330      1.1  christos   else
    331      1.1  christos     padding = 0;
    332      1.1  christos 
    333      1.1  christos   len += padding;
    334      1.1  christos 
    335      1.1  christos   ptr = frag_more (sizeof (uint32_t) + sizeof (uint32_t) + len);
    336      1.1  christos 
    337      1.1  christos   bfd_putl32 (DEBUG_S_SYMBOLS, ptr);
    338      1.1  christos   ptr += sizeof (uint32_t);
    339      1.1  christos   bfd_putl32 (len, ptr);
    340      1.1  christos   ptr += sizeof (uint32_t);
    341      1.1  christos 
    342      1.1  christos   /* Write S_OBJNAME entry.  */
    343      1.1  christos 
    344      1.1  christos   bfd_putl16 (sizeof (struct OBJNAMESYM) - sizeof (uint16_t) + path_len + 1,
    345      1.1  christos 	      &objname.length);
    346      1.1  christos   bfd_putl16 (S_OBJNAME, &objname.type);
    347      1.1  christos   bfd_putl32 (0, &objname.signature);
    348      1.1  christos 
    349      1.1  christos   memcpy (ptr, &objname, sizeof (struct OBJNAMESYM));
    350      1.1  christos   ptr += sizeof (struct OBJNAMESYM);
    351      1.1  christos   memcpy (ptr, path, path_len + 1);
    352      1.1  christos   ptr += path_len + 1;
    353      1.1  christos 
    354      1.1  christos   free (path);
    355      1.1  christos 
    356      1.1  christos   /* Write S_COMPILE3 entry.  */
    357      1.1  christos 
    358      1.1  christos   bfd_putl16 (sizeof (struct COMPILESYM3) - sizeof (uint16_t)
    359      1.1  christos 	      + sizeof (assembler) + padding, &compile3.length);
    360      1.1  christos   bfd_putl16 (S_COMPILE3, &compile3.type);
    361      1.1  christos   bfd_putl32 (CV_CFL_MASM, &compile3.flags);
    362      1.1  christos   bfd_putl16 (target_processor (), &compile3.machine);
    363      1.1  christos   bfd_putl16 (0, &compile3.frontend_major);
    364      1.1  christos   bfd_putl16 (0, &compile3.frontend_minor);
    365      1.1  christos   bfd_putl16 (0, &compile3.frontend_build);
    366      1.1  christos   bfd_putl16 (0, &compile3.frontend_qfe);
    367      1.1  christos   bfd_putl16 (0, &compile3.backend_major);
    368      1.1  christos   bfd_putl16 (0, &compile3.backend_minor);
    369      1.1  christos   bfd_putl16 (0, &compile3.backend_build);
    370      1.1  christos   bfd_putl16 (0, &compile3.backend_qfe);
    371      1.1  christos 
    372      1.1  christos   memcpy (ptr, &compile3, sizeof (struct COMPILESYM3));
    373      1.1  christos   ptr += sizeof (struct COMPILESYM3);
    374      1.1  christos   memcpy (ptr, assembler, sizeof (assembler));
    375      1.1  christos   ptr += sizeof (assembler);
    376      1.1  christos 
    377      1.1  christos   memset (ptr, 0, padding);
    378      1.1  christos }
    379      1.1  christos 
    380      1.1  christos /* Processing of the file has finished, emit the .debug$S section.  */
    381      1.1  christos void
    382      1.1  christos codeview_finish (void)
    383      1.1  christos {
    384      1.1  christos   segT seg;
    385      1.1  christos 
    386      1.1  christos   if (!blocks_head)
    387      1.1  christos     return;
    388      1.1  christos 
    389      1.1  christos   seg = subseg_new (".debug$S", 0);
    390      1.1  christos 
    391      1.1  christos   bfd_set_section_flags (seg, SEC_READONLY | SEC_NEVER_LOAD);
    392      1.1  christos 
    393      1.1  christos   bfd_putl32 (CV_SIGNATURE_C13, frag_more (sizeof (uint32_t)));
    394      1.1  christos 
    395      1.1  christos   write_string_table ();
    396      1.1  christos   write_checksums ();
    397      1.1  christos   write_lines_info ();
    398      1.1  christos   write_symbols_info ();
    399      1.1  christos }
    400      1.1  christos 
    401      1.1  christos /* Assign a new index number for the given file, or return the existing
    402      1.1  christos    one if already assigned.  */
    403      1.1  christos static unsigned int
    404      1.1  christos get_fileno (const char *file)
    405      1.1  christos {
    406      1.1  christos   struct source_file *sf;
    407      1.1  christos   char *path = lrealpath (file);
    408      1.1  christos   char *path2 = remap_debug_filename (path);
    409      1.1  christos   size_t path_len;
    410      1.1  christos   FILE *f;
    411      1.1  christos 
    412      1.1  christos   free (path);
    413      1.1  christos   path = path2;
    414      1.1  christos 
    415      1.1  christos   path_len = strlen (path);
    416      1.1  christos 
    417      1.1  christos   for (sf = files_head; sf; sf = sf->next)
    418      1.1  christos     {
    419      1.1  christos       if (path_len == strlen (sf->filename)
    420      1.1  christos 	  && !filename_ncmp (sf->filename, path, path_len))
    421      1.1  christos 	{
    422      1.1  christos 	  free (path);
    423      1.1  christos 	  return sf->num;
    424      1.1  christos 	}
    425      1.1  christos     }
    426      1.1  christos 
    427      1.1  christos   sf = xmalloc (sizeof (struct source_file));
    428      1.1  christos 
    429      1.1  christos   sf->next = NULL;
    430      1.1  christos   sf->num = num_source_files;
    431      1.1  christos   sf->filename = path;
    432      1.1  christos 
    433      1.1  christos   f = fopen (file, "r");
    434      1.1  christos   if (!f)
    435      1.1  christos     as_fatal (_("could not open %s for reading"), file);
    436      1.1  christos 
    437      1.1  christos   if (md5_stream (f, sf->md5))
    438      1.1  christos     {
    439      1.1  christos       fclose(f);
    440      1.1  christos       as_fatal (_("md5_stream failed"));
    441      1.1  christos     }
    442      1.1  christos 
    443      1.1  christos   fclose(f);
    444      1.1  christos 
    445      1.1  christos   if (!files_head)
    446      1.1  christos     files_head = sf;
    447      1.1  christos   else
    448      1.1  christos     files_tail->next = sf;
    449      1.1  christos 
    450      1.1  christos   files_tail = sf;
    451      1.1  christos 
    452      1.1  christos   num_source_files++;
    453      1.1  christos 
    454      1.1  christos   return num_source_files - 1;
    455      1.1  christos }
    456      1.1  christos 
    457      1.1  christos /* Called for each new line in asm file.  */
    458      1.1  christos void
    459      1.1  christos codeview_generate_asm_lineno (void)
    460      1.1  christos {
    461      1.1  christos   const char *file;
    462      1.1  christos   unsigned int filenr;
    463      1.1  christos   unsigned int lineno;
    464      1.1  christos   struct line *l;
    465      1.1  christos   symbolS *sym = NULL;
    466      1.1  christos   struct line_block *lb;
    467      1.1  christos   struct line_file *lf;
    468      1.1  christos 
    469      1.1  christos   file = as_where (&lineno);
    470      1.1  christos 
    471      1.1  christos   filenr = get_fileno (file);
    472      1.1  christos 
    473      1.1  christos   if (!blocks_tail || blocks_tail->frag != frag_now)
    474      1.1  christos     {
    475      1.1  christos       static int label_num = 0;
    476      1.1  christos       char name[32];
    477      1.1  christos 
    478      1.1  christos       sprintf (name, ".Loc.%u", label_num);
    479      1.1  christos       label_num++;
    480      1.1  christos       sym = symbol_new (name, now_seg, frag_now, frag_now_fix ());
    481      1.1  christos 
    482      1.1  christos       lb = xmalloc (sizeof (struct line_block));
    483      1.1  christos       lb->next = NULL;
    484      1.1  christos       lb->seg = now_seg;
    485      1.1  christos       lb->subseg = now_subseg;
    486      1.1  christos       lb->frag = frag_now;
    487      1.1  christos       lb->sym = sym;
    488      1.1  christos       lb->files_head = lb->files_tail = NULL;
    489      1.1  christos 
    490      1.1  christos       if (!blocks_head)
    491      1.1  christos 	blocks_head = lb;
    492      1.1  christos       else
    493      1.1  christos 	blocks_tail->next = lb;
    494      1.1  christos 
    495      1.1  christos       blocks_tail = lb;
    496      1.1  christos     }
    497      1.1  christos   else
    498      1.1  christos     {
    499      1.1  christos       lb = blocks_tail;
    500      1.1  christos     }
    501      1.1  christos 
    502      1.1  christos   if (!lb->files_tail || lb->files_tail->fileno != filenr)
    503      1.1  christos     {
    504      1.1  christos       lf = xmalloc (sizeof (struct line_file));
    505      1.1  christos       lf->next = NULL;
    506      1.1  christos       lf->fileno = filenr;
    507      1.1  christos       lf->lines_head = lf->lines_tail = NULL;
    508      1.1  christos       lf->num_lines = 0;
    509      1.1  christos 
    510      1.1  christos       if (!lb->files_head)
    511      1.1  christos 	lb->files_head = lf;
    512      1.1  christos       else
    513      1.1  christos 	lb->files_tail->next = lf;
    514      1.1  christos 
    515      1.1  christos       lb->files_tail = lf;
    516      1.1  christos     }
    517      1.1  christos   else
    518      1.1  christos     {
    519      1.1  christos       lf = lb->files_tail;
    520      1.1  christos     }
    521      1.1  christos 
    522      1.1  christos   l = xmalloc (sizeof (struct line));
    523      1.1  christos   l->next = NULL;
    524      1.1  christos   l->lineno = lineno;
    525      1.1  christos   l->frag_offset = frag_now_fix ();
    526      1.1  christos 
    527      1.1  christos   if (!lf->lines_head)
    528      1.1  christos     lf->lines_head = l;
    529      1.1  christos   else
    530      1.1  christos     lf->lines_tail->next = l;
    531      1.1  christos 
    532      1.1  christos   lf->lines_tail = l;
    533      1.1  christos   lf->num_lines++;
    534      1.1  christos }
    535      1.1  christos 
    536  1.1.1.2  christos /* Output a compressed CodeView integer.  The return value is the number of
    537  1.1.1.2  christos    bytes used.  */
    538  1.1.1.2  christos 
    539  1.1.1.2  christos unsigned int
    540  1.1.1.2  christos output_cv_comp (char *p, offsetT value, int sign)
    541  1.1.1.2  christos {
    542  1.1.1.2  christos   char *orig = p;
    543  1.1.1.2  christos 
    544  1.1.1.2  christos   if (sign)
    545  1.1.1.2  christos     {
    546  1.1.1.2  christos       if (value < -0xfffffff || value > 0xfffffff)
    547  1.1.1.2  christos 	{
    548  1.1.1.2  christos 	  as_bad (_("value cannot be expressed as a .cv_scomp"));
    549  1.1.1.2  christos 	  return 0;
    550  1.1.1.2  christos 	}
    551  1.1.1.2  christos     }
    552  1.1.1.2  christos   else
    553  1.1.1.2  christos     {
    554  1.1.1.2  christos       if (value < 0 || value > 0x1fffffff)
    555  1.1.1.2  christos 	{
    556  1.1.1.2  christos 	  as_bad (_("value cannot be expressed as a .cv_ucomp"));
    557  1.1.1.2  christos 	  return 0;
    558  1.1.1.2  christos 	}
    559  1.1.1.2  christos     }
    560  1.1.1.2  christos 
    561  1.1.1.2  christos   if (sign)
    562  1.1.1.2  christos     {
    563  1.1.1.2  christos       if (value >= 0)
    564  1.1.1.2  christos 	value <<= 1;
    565  1.1.1.2  christos       else
    566  1.1.1.2  christos 	value = (-value << 1) | 1;
    567  1.1.1.2  christos     }
    568  1.1.1.2  christos 
    569  1.1.1.2  christos   if (value <= 0x7f)
    570  1.1.1.2  christos     {
    571  1.1.1.2  christos       *p++ = value;
    572  1.1.1.2  christos     }
    573  1.1.1.2  christos   else if (value <= 0x3fff)
    574  1.1.1.2  christos     {
    575  1.1.1.2  christos       *p++ = 0x80 | (value >> 8);
    576  1.1.1.2  christos       *p++ = value & 0xff;
    577  1.1.1.2  christos     }
    578  1.1.1.2  christos   else
    579  1.1.1.2  christos     {
    580  1.1.1.2  christos       *p++ = 0xc0 | (value >> 24);
    581  1.1.1.2  christos       *p++ = (value >> 16) & 0xff;
    582  1.1.1.2  christos       *p++ = (value >> 8) & 0xff;
    583  1.1.1.2  christos       *p++ = value & 0xff;
    584  1.1.1.2  christos     }
    585  1.1.1.2  christos 
    586  1.1.1.2  christos   return p - orig;
    587  1.1.1.2  christos }
    588  1.1.1.2  christos 
    589  1.1.1.2  christos /* Return the size needed to output a compressed CodeView integer.  */
    590  1.1.1.2  christos 
    591  1.1.1.2  christos unsigned int
    592  1.1.1.2  christos sizeof_cv_comp (offsetT value, int sign)
    593  1.1.1.2  christos {
    594  1.1.1.2  christos   if (sign)
    595  1.1.1.2  christos     {
    596  1.1.1.2  christos       if (value < -0xfffffff || value > 0xfffffff)
    597  1.1.1.2  christos 	return 0;
    598  1.1.1.2  christos 
    599  1.1.1.2  christos       if (value >= 0)
    600  1.1.1.2  christos 	value <<= 1;
    601  1.1.1.2  christos       else
    602  1.1.1.2  christos 	value = (-value << 1) | 1;
    603  1.1.1.2  christos     }
    604  1.1.1.2  christos   else
    605  1.1.1.2  christos     {
    606  1.1.1.2  christos       if (value > 0x1fffffff)
    607  1.1.1.2  christos 	return 0;
    608  1.1.1.2  christos     }
    609  1.1.1.2  christos 
    610  1.1.1.2  christos   if (value <= 0x7f)
    611  1.1.1.2  christos     return 1;
    612  1.1.1.2  christos   else if (value <= 0x3fff)
    613  1.1.1.2  christos     return 2;
    614  1.1.1.2  christos   else if (value <= 0x1fffffff)
    615  1.1.1.2  christos     return 4;
    616  1.1.1.2  christos   else
    617  1.1.1.2  christos     return 0;
    618  1.1.1.2  christos }
    619  1.1.1.2  christos 
    620      1.1  christos #else
    621      1.1  christos 
    622      1.1  christos void
    623      1.1  christos codeview_finish (void)
    624      1.1  christos {
    625      1.1  christos }
    626      1.1  christos 
    627      1.1  christos void
    628      1.1  christos codeview_generate_asm_lineno (void)
    629      1.1  christos {
    630      1.1  christos }
    631      1.1  christos 
    632      1.1  christos #endif /* TE_PE && O_secrel */
    633