mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
* 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:
parent
dc1f3d8a2d
commit
e8f5eee43d
@ -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.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user