1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #include "leaky.h"
6 
7 #ifdef USE_COFF
8 
9 #  define LANGUAGE_C
10 #  include <sym.h>
11 #  include <cmplrs/stsupport.h>
12 #  include <symconst.h>
13 #  include <filehdr.h>
14 #  include <ldfcn.h>
15 #  include <string.h>
16 #  include <stdlib.h>
17 
18 #  ifdef IRIX4
19 extern "C" {
20 extern char* demangle(char const* in);
21 };
22 #  else
23 #    include <dem.h>
24 #  endif
25 
Demangle(char * rawName)26 static char* Demangle(char* rawName) {
27 #  ifdef IRIX4
28   return strdup(demangle(rawName));
29 #  else
30   char namebuf[4000];
31   demangle(rawName, namebuf);
32   return strdup(namebuf);
33 #  endif
34 }
35 
readSymbols(const char * fileName)36 void leaky::readSymbols(const char* fileName) {
37   LDFILE* ldptr;
38 
39   ldptr = ldopen(fileName, nullptr);
40   if (!ldptr) {
41     fprintf(stderr, "%s: unable to open \"%s\"\n", applicationName, fileName);
42     exit(-1);
43   }
44   if (PSYMTAB(ldptr) == 0) {
45     fprintf(stderr, "%s: \"%s\": has no symbol table\n", applicationName,
46             fileName);
47     exit(-1);
48   }
49 
50   long isymMax = SYMHEADER(ldptr).isymMax;
51   long iextMax = SYMHEADER(ldptr).iextMax;
52   long iMax = isymMax + iextMax;
53 
54   long alloced = 10000;
55   Symbol* syms = (Symbol*)malloc(sizeof(Symbol) * 10000);
56   Symbol* sp = syms;
57   Symbol* last = syms + alloced;
58   SYMR symr;
59 
60   for (long isym = 0; isym < iMax; isym++) {
61     if (ldtbread(ldptr, isym, &symr) != SUCCESS) {
62       fprintf(stderr, "%s: can't read symbol #%d\n", applicationName, isym);
63       exit(-1);
64     }
65     if (isym < isymMax) {
66       if ((symr.st == stStaticProc) ||
67           ((symr.st == stProc) &&
68            ((symr.sc == scText) || (symr.sc == scAbs))) ||
69           ((symr.st == stBlock) && (symr.sc == scText))) {
70         // Text symbol. Set name field to point to the symbol name
71         sp->name = Demangle(ldgetname(ldptr, &symr));
72         sp->address = symr.value;
73         sp++;
74         if (sp >= last) {
75           long n = alloced + 10000;
76           syms = (Symbol*)realloc(syms, (size_t)(sizeof(Symbol) * n));
77           last = syms + n;
78           sp = syms + alloced;
79           alloced = n;
80         }
81       }
82     }
83   }
84 
85   int interesting = sp - syms;
86   if (!quiet) {
87     printf("Total of %d symbols\n", interesting);
88   }
89   usefulSymbols = interesting;
90   externalSymbols = syms;
91 }
92 
93 #endif /* USE_COFF */
94