* objdump.c: Include sys/mman.h

(print_file_list): Remove f, add map, mapsize, linemap, maxline, last_line, first fields.
  (slurp_file): Add.
  (index_file): Add.
  (print_file_open): Call slurp_file and index_file. Initialize new fields.
  (skip_to_line): Rename to print_line and write only single line.
  (dump_line): Add.
  (show_line): Change to new algorithm.
This commit is contained in:
Nick Clifton 2007-06-18 16:38:49 +00:00
parent dc1f3d8a2d
commit e8f5eee43d
2 changed files with 164 additions and 97 deletions

View File

@ -1,3 +1,16 @@
2007-06-18 Andi Kleen <ak@suse.de>
* objdump.c: Include sys/mman.h
(print_file_list): Remove f, add map, mapsize, linemap, maxline,
last_line, first fields.
(slurp_file): Add.
(index_file): Add.
(print_file_open): Call slurp_file and index_file. Initialize new
fields.
(skip_to_line): Rename to print_line and write only single line.
(dump_line): Add.
(show_line): Change to new algorithm.
2007-06-18 Thomas Weidenmueller <w3seek@reactos.org>
* resres.c (probe_binary): Fix test for badly formatted headers.

View File

@ -61,6 +61,10 @@
#include "debug.h"
#include "budbg.h"
#ifdef HAVE_MMAP
#include <sys/mman.h>
#endif
/* Internal headers for the ELF .stab-dump code - sorry. */
#define BYTES_IN_WORD 32
#include "aout/aout64.h"
@ -927,8 +931,12 @@ struct print_file_list
struct print_file_list *next;
const char *filename;
const char *modname;
unsigned int line;
FILE *f;
const char *map;
size_t mapsize;
const char **linemap;
unsigned maxline;
unsigned last_line;
int first;
};
static struct print_file_list *print_files;
@ -938,6 +946,99 @@ static struct print_file_list *print_files;
#define SHOW_PRECEDING_CONTEXT_LINES (5)
/* Read a complete file into memory. */
static const char *
slurp_file (const char *fn, size_t *size)
{
#ifdef HAVE_MMAP
int ps = getpagesize ();
size_t msize;
#endif
const char *map;
struct stat st;
int fd = open (fn, O_RDONLY);
if (fd < 0)
return NULL;
if (fstat (fd, &st) < 0)
return NULL;
*size = st.st_size;
#ifdef HAVE_MMAP
msize = (*size + ps - 1) & ~(ps - 1);
map = mmap (NULL, msize, PROT_READ, MAP_SHARED, fd, 0);
if (map != (char *)-1L)
{
close(fd);
return map;
}
#endif
map = malloc (*size);
if (!map || (size_t) read (fd, (char *)map, *size) != *size)
{
free ((void *)map);
map = NULL;
}
close (fd);
return map;
}
#define line_map_decrease 5
/* Precompute array of lines for a mapped file. */
static const char **
index_file (const char *map, size_t size, unsigned int *maxline)
{
const char *p, *lstart, *end;
int chars_per_line = 45; /* First iteration will use 40. */
unsigned int lineno;
const char **linemap = NULL;
unsigned long line_map_size = 0;
lineno = 0;
lstart = map;
end = map + size;
for (p = map; p < end; p++)
{
if (*p == '\n')
{
if (p + 1 < end && p[1] == '\r')
p++;
}
else if (*p == '\r')
{
if (p + 1 < end && p[1] == '\n')
p++;
}
else
continue;
/* End of line found. */
if (linemap == NULL || line_map_size < lineno + 1)
{
unsigned long newsize;
chars_per_line -= line_map_decrease;
if (chars_per_line <= 1)
chars_per_line = 1;
line_map_size = size / chars_per_line + 1;
if (line_map_size < lineno + 1)
line_map_size = lineno + 1;
newsize = line_map_size * sizeof (char *);
linemap = xrealloc (linemap, newsize);
}
linemap[lineno++] = lstart;
lstart = p + 1;
}
*maxline = lineno;
return linemap;
}
/* Tries to open MODNAME, and if successful adds a node to print_files
linked list and returns that node. Returns NULL on failure. */
@ -945,24 +1046,22 @@ static struct print_file_list *
try_print_file_open (const char *origname, const char *modname)
{
struct print_file_list *p;
FILE *f;
f = fopen (modname, "r");
if (f == NULL)
return NULL;
if (print_files != NULL && print_files->f != NULL)
{
fclose (print_files->f);
print_files->f = NULL;
}
p = xmalloc (sizeof (struct print_file_list));
p->map = slurp_file (modname, &p->mapsize);
if (p->map == NULL)
{
free (p);
return NULL;
}
p->linemap = index_file (p->map, p->mapsize, &p->maxline);
p->last_line = 0;
p->filename = origname;
p->modname = modname;
p->line = 0;
p->f = f;
p->next = print_files;
p->first = 1;
print_files = p;
return p;
}
@ -1021,29 +1120,32 @@ update_source_path (const char *filename)
return NULL;
}
/* Skip ahead to a given line in a file, optionally printing each
line. */
/* Print a source file line. */
static void
print_line (struct print_file_list *p, unsigned int line)
{
const char *l;
--line;
if (line >= p->maxline)
return;
l = p->linemap [line];
fwrite (l, 1, strcspn (l, "\n\r"), stdout);
putchar ('\n');
}
/* Print a range of source code lines. */
static void
skip_to_line (struct print_file_list *p, unsigned int line,
bfd_boolean show)
dump_lines (struct print_file_list *p, unsigned int start, unsigned int end)
{
while (p->line < line)
if (p->map == NULL)
return;
while (start <= end)
{
char buf[100];
if (fgets (buf, sizeof buf, p->f) == NULL)
{
fclose (p->f);
p->f = NULL;
break;
}
if (show)
printf ("%s", buf);
if (strchr (buf, '\n') != NULL)
++p->line;
print_line (p, start);
start++;
}
}
@ -1084,79 +1186,31 @@ show_line (bfd *abfd, asection *section, bfd_vma addr_offset)
&& line > 0)
{
struct print_file_list **pp, *p;
unsigned l;
for (pp = &print_files; *pp != NULL; pp = &(*pp)->next)
if (strcmp ((*pp)->filename, filename) == 0)
break;
p = *pp;
if (p != NULL)
{
if (p != print_files)
{
int l;
/* We have reencountered a file name which we saw
earlier. This implies that either we are dumping out
code from an included file, or the same file was
linked in more than once. There are two common cases
of an included file: inline functions in a header
file, and a bison or flex skeleton file. In the
former case we want to just start printing (but we
back up a few lines to give context); in the latter
case we want to continue from where we left off. I
can't think of a good way to distinguish the cases,
so I used a heuristic based on the file name. */
if (strcmp (p->filename + strlen (p->filename) - 2, ".h") != 0)
l = p->line;
else
{
l = line - SHOW_PRECEDING_CONTEXT_LINES;
if (l < 0)
l = 0;
}
if (p->f == NULL)
{
p->f = fopen (p->modname, "r");
p->line = 0;
}
if (p->f != NULL)
skip_to_line (p, l, FALSE);
if (print_files->f != NULL)
{
fclose (print_files->f);
print_files->f = NULL;
}
}
if (p->f != NULL)
{
skip_to_line (p, line, TRUE);
*pp = p->next;
p->next = print_files;
print_files = p;
}
}
else
{
if (p == NULL)
p = update_source_path (filename);
if (p != NULL)
if (p != NULL && line != p->last_line)
{
if (file_start_context && p->first)
l = 1;
else
{
int l;
if (file_start_context)
l = 0;
else
l = line - SHOW_PRECEDING_CONTEXT_LINES;
if (l < 0)
l = 0;
skip_to_line (p, l, FALSE);
if (p->f != NULL)
skip_to_line (p, line, TRUE);
l = line - SHOW_PRECEDING_CONTEXT_LINES;
if (l >= line)
l = 1;
if (p->last_line >= l && p->last_line <= line)
l = p->last_line + 1;
}
dump_lines (p, l, line);
p->last_line = line;
p->first = 0;
}
}