Remove files which are no longer needed.
This commit is contained in:
parent
35a9b11d37
commit
d1156ed625
28 changed files with 0 additions and 8915 deletions
|
|
@ -1,339 +0,0 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
675 Mass Ave, Cambridge, MA 02139, USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Appendix: How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
# file crs/Makefile
|
||||
|
||||
top_srcdir= @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
MACHINE = @MACHINE@
|
||||
|
||||
# Programs used by "make":
|
||||
#
|
||||
CC = @CC@
|
||||
DEFS = -D$(MACHINE)
|
||||
CFLAGS = -I../h -I$(top_srcdir)/h -I$(top_srcdir)/gmp @CFLAGS@ $(DEFS)
|
||||
|
||||
SHELL = /bin/sh
|
||||
RM = @RM@
|
||||
|
||||
# Files
|
||||
|
||||
OBJS = dld.o @SETJMPO@ socket.o
|
||||
HFILES = ../h/config.h $(srcdir)/objff.h
|
||||
TARGETS = ../libcrs.a @RSYM@
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
../libcrs.a: $(OBJS)
|
||||
ar r $@ $(OBJS)
|
||||
@RANLIB@ $@
|
||||
|
||||
dld.o: $(srcdir)/@DLD@.c $(HFILES)
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/@DLD@.c -o $@
|
||||
|
||||
socket.o: $(srcdir)/socket.c
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/socket.c -o $@
|
||||
|
||||
unexec.o: $(srcdir)/@UNEXEC@.c $(HFILES)
|
||||
$(CC) -c $(CFLAGS) $(srcdir)/@UNEXEC@.c -o $@
|
||||
|
||||
setjmp.o: $(srcdir)/@SETJMP@
|
||||
as $(srcdir)/@SETJMP@ -o $@
|
||||
|
||||
rsym rsym.exe: $(srcdir)/rsym.c $(top_srcdir)/h/machines.h
|
||||
${CC} ${CFLAGS} $(srcdir)/rsym.c -o $@
|
||||
|
||||
clean:
|
||||
$(RM) $(TARGETS) $(OBJS) core a.out
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
This directory contains the components of the Common Runtime Support:
|
||||
|
||||
1. memory management (files gbc.c alloc.c)
|
||||
2. dumping an image (files unex*.c and unixsave.c)
|
||||
3. dynamic loading (dld.c)
|
||||
4. networking support (tcp.c)
|
||||
|
||||
These are built into a library (libcrs.a) which is searched when
|
||||
building a Lisp application.
|
||||
|
||||
Implementations of unexec for various architectures is provided.
|
||||
Some of them are those provided with GNU Emacs.
|
||||
However we cannot use for instance unexsunos4, which expects a dynamic
|
||||
linked executable, since this prevents subsequent loading of files
|
||||
(procedures such as memcpy and _setjmp do not appear in the load map).
|
||||
|
||||
As a fall back we use unixsave.c, which works for all Suns, HP9000/300,
|
||||
Vax, DOS/go32, Apollo, IBM/RT, Sequent.
|
||||
1484
src/crs/dld.c
1484
src/crs/dld.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,230 +0,0 @@
|
|||
/* dldNeXT.c -- Dynamic loader for NeXT */
|
||||
/*
|
||||
Copyright (c) 1994, Giuseppe Attardi
|
||||
|
||||
This file is part of ECoLisp, an Embeddable Common Lisp.
|
||||
ECoLisp is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
|
||||
#include "ecls.h"
|
||||
#include <rld.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef THREADS
|
||||
static int code_size;
|
||||
static char *code_start;
|
||||
#endif
|
||||
|
||||
static unsigned long
|
||||
alloc_code_block(unsigned long size, unsigned long headers_size) {
|
||||
code_size = size;
|
||||
code_start = (char *)alloc_contblock(size);
|
||||
return (unsigned long)code_start;
|
||||
}
|
||||
|
||||
static void
|
||||
load_mach_o(char *filename)
|
||||
{
|
||||
FILE *fp;
|
||||
struct mach_header header;
|
||||
char *hdrbuf;
|
||||
struct load_command *load_command;
|
||||
struct segment_command *segment_command;
|
||||
struct section *section;
|
||||
int len, cmd, seg;
|
||||
|
||||
if ((fp = fopen(filename, "r")) == NULL)
|
||||
FEerror("Can't read Mach-O object file", 0);
|
||||
len = fread((char *)&header, sizeof(struct mach_header), 1, fp);
|
||||
if (len == 1 && header.magic == MH_MAGIC) {
|
||||
hdrbuf = (char *)malloc(header.sizeofcmds);
|
||||
len = fread(hdrbuf, header.sizeofcmds, 1, fp);
|
||||
if (len != 1)
|
||||
FEerror("failure reading Mach-O load commands", 0);
|
||||
load_command = (struct load_command *) hdrbuf;
|
||||
for (cmd = 0; cmd < header.ncmds; ++cmd) {
|
||||
if (load_command->cmd == LC_SEGMENT) {
|
||||
segment_command = (struct segment_command *) load_command;
|
||||
section = (struct section *) ((char *)(segment_command + 1));
|
||||
for (seg = 0; seg < segment_command->nsects; ++seg, ++section) {
|
||||
if (section->size != 0 && section->offset != 0) {
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "section: %s, addr: 0x%08x, size: %d\n",
|
||||
section->sectname, section->addr, section->size);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
fseek(fp, section->offset, 0);
|
||||
fread((char *)section->addr, section->size, 1, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
load_command = (struct load_command *)
|
||||
((char *)load_command + load_command->cmdsize);
|
||||
}
|
||||
free(hdrbuf);
|
||||
}
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* dld --
|
||||
* dynamically load a file into memory.
|
||||
*
|
||||
* Results:
|
||||
* none.
|
||||
*
|
||||
* Side effects:
|
||||
* codeblock: containing address where the code has been loaded, and
|
||||
* its size
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
dld(char *faslfile, struct codeblock *Cblock)
|
||||
{
|
||||
struct mach_header *hdr;
|
||||
char *files[2] = {faslfile, 0};
|
||||
char tempfile[40];
|
||||
|
||||
rld_address_func(alloc_code_block);
|
||||
sprintf(tempfile, "/tmp/fasltemp%d", getpid());
|
||||
if (!rld_load(NULL, &hdr, files, tempfile))
|
||||
FEerror(";;; rld_load() failed", 0);
|
||||
load_mach_o(tempfile);
|
||||
unlink(tempfile);
|
||||
Cblock->cd_size = code_size;
|
||||
Cblock->cd_start = code_start;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* faslink --
|
||||
* dynamically load a file into memory, linking it with additional
|
||||
* libraries.
|
||||
*
|
||||
* Results:
|
||||
* none.
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static char *library_search_path[] =
|
||||
{"/lib", "/usr/lib", "/usr/local/lib", NULL};
|
||||
|
||||
#define strdup(string) strcpy((char *)malloc(strlen(string)+1),(string))
|
||||
|
||||
static char*
|
||||
expand_library_filename(char *filename)
|
||||
{
|
||||
int fd;
|
||||
char **dir;
|
||||
char libname[256];
|
||||
char fullname[256];
|
||||
|
||||
if (filename[0] == '-' && filename[1] == 'l') {
|
||||
filename +=2;
|
||||
strcpy(libname, "lib");
|
||||
strcat(libname, filename);
|
||||
strcat(libname, ".a");
|
||||
for (dir = library_search_path; *dir; dir++) {
|
||||
strcpy(fullname, *dir);
|
||||
strcat(fullname, "/");
|
||||
strcat(fullname, libname);
|
||||
if ((fd = open(fullname, O_RDONLY, 0)) > 0) {
|
||||
close(fd);
|
||||
return (strdup(fullname));
|
||||
}
|
||||
}
|
||||
return (strdup(libname));
|
||||
}
|
||||
return (strdup(filename));
|
||||
}
|
||||
|
||||
static char**
|
||||
make_ofile_list(char *faslfile, char *argstr)
|
||||
{
|
||||
char filename[256];
|
||||
char *dst;
|
||||
int i;
|
||||
char **ofile_list;
|
||||
|
||||
ofile_list = (char **)calloc(1, sizeof(char *));
|
||||
ofile_list[0] = strdup(faslfile);
|
||||
i = 1;
|
||||
if (argstr != NULL) {
|
||||
for (;; i++) {
|
||||
while ((*argstr == ' ') && (*argstr != '\0'))
|
||||
argstr++;
|
||||
if (*argstr == '\0')
|
||||
break;
|
||||
dst = filename;
|
||||
while ((*argstr != ' ') && (*argstr != '\0'))
|
||||
*dst++ = *argstr++;
|
||||
*dst = '\0';
|
||||
ofile_list = (char **)realloc((void *)ofile_list,
|
||||
(i + 1) * sizeof(char *));
|
||||
ofile_list[i] = expand_library_filename(filename);
|
||||
}
|
||||
}
|
||||
ofile_list = (char **)realloc((void *)ofile_list, (i + 1) * sizeof(char *));
|
||||
ofile_list[i] = NULL;
|
||||
return (ofile_list);
|
||||
}
|
||||
|
||||
static void
|
||||
free_ofile_list(char **ofile_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1;; i++) {
|
||||
if (ofile_list[i] == NULL)
|
||||
break;
|
||||
(void)free(ofile_list[i]);
|
||||
}
|
||||
(void)free(ofile_list);
|
||||
}
|
||||
|
||||
int
|
||||
faslink(object faslfile, object ldargstring)
|
||||
{
|
||||
object temp_cfun, dataStream;
|
||||
struct codeblock Cblock;
|
||||
char *faslfilename;
|
||||
char *ldargstr;
|
||||
char **ofiles;
|
||||
struct mach_header *hdr;
|
||||
|
||||
ldargstr = coerce_to_filename(ldargstring);
|
||||
faslfilename = coerce_to_filename(faslfile);
|
||||
|
||||
printf(";;; Linking %s\n", faslfilename);
|
||||
rld_address_func(alloc_code_block);
|
||||
ofiles = make_ofile_list(faslfilename, ldargstr);
|
||||
if (!rld_load(NULL, &hdr, ofiles, NULL)) {
|
||||
free_ofile_list(ofiles);
|
||||
FEerror(";;; rld_load() failed", 0);
|
||||
}
|
||||
free_ofile_list(ofiles);
|
||||
/* preserve Cblock from GC */
|
||||
temp_cfun = alloc_object(t_cfun);
|
||||
temp_cfun->cf.cf_name = OBJNULL;
|
||||
temp_cfun->cf.cf_block = &Cblock;
|
||||
Cblock.cd_size = code_size;
|
||||
Cblock.cd_start = code_start;
|
||||
Cblock.cd_data = OBJNULL;
|
||||
|
||||
dataStream = (object)open_fasl_data(faslfile);
|
||||
|
||||
asm("trap #2"); /* clear cache */
|
||||
(*(int (*)())(Cblock.cd_start))(Cblock.cd_size, dataStream);
|
||||
close_stream(dataStream, TRUE);
|
||||
|
||||
return(0);
|
||||
}
|
||||
248
src/crs/objff.h
248
src/crs/objff.h
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 1990, Giuseppe Attardi and William F. Schelter.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
/* format of a rsyms output file:
|
||||
|
||||
struct lsymbol_table (gives number of symbols, and sum of length of strings)
|
||||
addr, char[], addr, char[], ...
|
||||
This can be read since the addr is sizeof(int) and the char[] is null
|
||||
terminated, immediately followed by and addr...
|
||||
There are tab.n_symbols pairs occurring.
|
||||
|
||||
*/
|
||||
|
||||
struct lsymbol_table {
|
||||
unsigned int n_symbols;
|
||||
unsigned int tot_leng;
|
||||
};
|
||||
|
||||
#ifdef COFF
|
||||
|
||||
# ifdef MSDOS
|
||||
# include <coff.h>
|
||||
# else
|
||||
# include <filehdr.h>
|
||||
# include <aouthdr.h>
|
||||
# include <scnhdr.h>
|
||||
# include <syms.h>
|
||||
# include <reloc.h>
|
||||
# endif MSDOS
|
||||
|
||||
# ifndef FILHDR
|
||||
# define FILHDR struct header
|
||||
# endif FILHDR
|
||||
|
||||
# undef N_BADMAG /* checks AOUTHDR instead of FILHDR */
|
||||
|
||||
# ifdef __i386__
|
||||
# define N_BADMAG(x) I386BADMAG(x)
|
||||
# elif defined(hpux)
|
||||
# define N_BADMAG(x) !(ISCOFF(x.a_magic))
|
||||
# else
|
||||
# define N_BADMAG(x) !(ISCOFF(x.f_magic))
|
||||
# endif
|
||||
|
||||
# ifdef ECOFF
|
||||
# undef N_TXTOFF
|
||||
# endif
|
||||
|
||||
# define N_TXTOFF(p) section[0].s_scnptr
|
||||
# define N_SYMOFF(x) (x).f_symptr
|
||||
# define NSYMS(x) (x).f_nsyms
|
||||
|
||||
# ifdef apollo
|
||||
# define EXT_and_TEXT_BSS_DAT(p) \
|
||||
((1 <= (p)->n_scnum) && ((p)->n_scnum <= 5) && (p)->n_sclass == C_EXT)
|
||||
# elif defined(ECOFF)
|
||||
# define EXT_and_TEXT_BSS_DAT(p) 1
|
||||
# else
|
||||
# define EXT_and_TEXT_BSS_DAT(p) \
|
||||
((1 <= (p)->n_scnum) && ((p)->n_scnum <= 3) && (p)->n_sclass == C_EXT)
|
||||
# endif apollo
|
||||
|
||||
|
||||
# ifdef ECOFF
|
||||
# define SYMENT EXTR
|
||||
# define SYMESZ sizeof(SYMENT)
|
||||
# define SYM_VALUE(sym) (sym).asym.value
|
||||
# define SYM_TYPE(psym) (psym)->asym.st
|
||||
# define SYM_NAME(psym) &string_table[(psym)->asym.iss]
|
||||
|
||||
/*
|
||||
We must distinguish the following kind of symbols:
|
||||
|
||||
External (ouside function bodies)
|
||||
Defined (in this file)
|
||||
Static (declared static)
|
||||
Exported (non declared static)
|
||||
Undefined
|
||||
|
||||
Unfortunately AS and GAS produce different symbol tables, so we find
|
||||
a common denominator as follows:
|
||||
|
||||
External: stNil || stGlobal || stProc || stStaticProc
|
||||
Undefined: stGblobal || (stProc && scUndefined)
|
||||
Defined: !Undefined
|
||||
Static: stNil || stStatic || stStaticProc
|
||||
Exported: !Static
|
||||
*/
|
||||
|
||||
# define C_STAT stNil: case stStatic: case stStaticProc
|
||||
# define C_EXT stGlobal: case stProc
|
||||
# define EXT_UNDEF(p) (SYM_TYPE(p) == stGlobal || \
|
||||
(SYM_TYPE(p) == stProc && (p)->asym.sc == scUndefined))
|
||||
# define EXT_EXPORTED(p) (SYM_TYPE(p) == stProc)
|
||||
# define NUM_AUX(p) 0
|
||||
|
||||
# else /* !ECOFF */
|
||||
|
||||
# define SYM_VALUE(sym) (sym).n_value
|
||||
# define SYM_TYPE(psym) (psym)->n_sclass
|
||||
# define SYM_NAME(psym) \
|
||||
(((psym)->n_zeroes == 0) ? \
|
||||
&string_table[(psym)->n_offset] : \
|
||||
((psym)->n_name[SYMNMLEN -1] ? \
|
||||
(strncpy(tem, (psym)->n_name, SYMNMLEN), (char *)tem) : \
|
||||
(psym)->n_name))
|
||||
|
||||
# define EXT_UNDEF(p) (((p)->n_scnum == 0) && (p)->n_sclass == C_EXT)
|
||||
|
||||
# define NUM_AUX(p) (p)->n_numaux
|
||||
|
||||
# endif ECOFF
|
||||
|
||||
# ifdef __GO32__
|
||||
# define n_name e.e_name
|
||||
# define n_numaux e_numaux
|
||||
# define n_offset e.e.e_offset
|
||||
# define n_sclass e_sclass
|
||||
# define n_scnum e_scnum
|
||||
# define n_type e_type
|
||||
# define n_value e_value
|
||||
# define n_zeroes e.e.e_zeroes
|
||||
# define SYMNMLEN E_SYMNMLEN
|
||||
|
||||
# define R_ABS 0
|
||||
# define R_RELBYTE 017
|
||||
# define R_RELWORD 020
|
||||
# define R_RELLONG 021
|
||||
# define R_PCRBYTE 022
|
||||
# define R_PCRWORD 023
|
||||
# define R_PCRLONG 024
|
||||
|
||||
# define R_DIR32 06
|
||||
|
||||
# endif __GO32__
|
||||
|
||||
#endif COFF
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
#ifdef ELF
|
||||
# define ELF_TARGET_ALL
|
||||
# include <elf.h>
|
||||
# define FILHDR Elf32_Ehdr
|
||||
# define PRGHDR Elf32_Phdr
|
||||
# define SCNHDR Elf32_Shdr
|
||||
# define SYMENT Elf32_Sym
|
||||
#ifdef __NetBSD__
|
||||
# define RELOC Elf32_RelA
|
||||
#else
|
||||
# define RELOC Elf32_Rela
|
||||
#endif
|
||||
# define N_BADMAG(h) (ELFMAG0 != h.e_ident[0])
|
||||
# ifdef __mips
|
||||
# define EXT_and_TEXT_BSS_DAT(p) ((ELF32_ST_BIND(p->st_info) == STB_GLOBAL) \
|
||||
&& (p->st_shndx == text_index \
|
||||
|| p->st_shndx == data_index\
|
||||
|| p->st_shndx == bss_index \
|
||||
|| p->st_shndx == 0xff00 \
|
||||
|| p->st_shndx == STN_UNDEF))
|
||||
# else
|
||||
# define EXT_and_TEXT_BSS_DAT(p) ((ELF32_ST_BIND(p->st_info) == STB_GLOBAL \
|
||||
|| ELF32_ST_BIND(p->st_info) == STB_WEAK) \
|
||||
&& (p->st_shndx == text_index \
|
||||
|| p->st_shndx == data_index\
|
||||
|| p->st_shndx == bss_index \
|
||||
|| p->st_shndx == SHN_UNDEF))
|
||||
# endif
|
||||
# define SYM_NAME(p) string_table+(p->st_name)
|
||||
# define SYM_VALUE(p) (p).st_value
|
||||
#endif ELF
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
#ifdef AOUT
|
||||
|
||||
# include AOUT
|
||||
|
||||
# define FILHDR struct exec
|
||||
|
||||
# ifndef AIX
|
||||
# define SYMENT struct nlist
|
||||
# endif AIX
|
||||
|
||||
# ifdef hpux
|
||||
# define nlist nlist_
|
||||
typedef struct syment {
|
||||
long n_value;
|
||||
unsigned char n_type;
|
||||
unsigned char n_length;
|
||||
short n_almod;
|
||||
short n_unused;
|
||||
union { long n_strx;} n_un;
|
||||
} SYMENT;
|
||||
# endif hpux
|
||||
|
||||
# ifndef SYMENT
|
||||
# define SYMENT struct syment
|
||||
# endif SYMENT
|
||||
|
||||
# ifndef SYMESZ
|
||||
# define SYMESZ (sizeof(SYMENT))
|
||||
# endif SYMESZ
|
||||
|
||||
# define SYM_VALUE(sym) (sym).n_value
|
||||
|
||||
# ifndef SYMNMLEN
|
||||
# define SYMNMLEN 0 /* no symbols are directly in the table */
|
||||
# endif SYMNMLEN
|
||||
|
||||
# ifdef hpux
|
||||
# define RELOC struct r_info
|
||||
# elif defined(__sparc__)
|
||||
# define RELOC struct reloc_info_sparc
|
||||
# else
|
||||
# define RELOC struct relocation_info
|
||||
# endif hpux
|
||||
|
||||
# ifdef hpux
|
||||
# define NSYMS(hdr) count_symbols(&hdr, fp)
|
||||
# define N_SYMOFF(x) LESYM_OFFSET(x)
|
||||
# define N_TRELOCOFF(x) RTEXT_OFFSET(x)
|
||||
# else
|
||||
# define NSYMS(f) ((unsigned int)((f).a_syms/(sizeof(struct nlist))))
|
||||
# define N_TRELOCOFF(x) (N_TXTOFF(x) + (x).a_text + (x).a_data)
|
||||
# endif hpux
|
||||
|
||||
# define EXT_UNDEF(p) ((p)->n_type == N_EXT)
|
||||
# define EXT_and_TEXT_BSS_DAT(p) (((p)->n_type & N_EXT) && \
|
||||
((p)->n_type & (N_TEXT | N_DATA | N_BSS)))
|
||||
# define NUM_AUX(p) 0
|
||||
# define SYM_TYPE(sym) ((sym)->n_type & N_TYPE)
|
||||
# define N_SECTION(sym) (SYM_TYPE(sym) & ~N_EXT)
|
||||
# define SYM_NAME(x) (string_table + (x)->n_un.n_strx)
|
||||
# define C_EXT N_UNDF
|
||||
# define RELSZ sizeof(RELOC)
|
||||
# ifndef N_MAGIC
|
||||
# define N_MAGIC(x) (x).a_magic
|
||||
# endif
|
||||
#endif AOUT
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
CC = gcc
|
||||
|
||||
unexe : unexe.c
|
||||
$(CC) -static -o unexe -g unexe.c ../../libcrs.a
|
||||
|
||||
ecoffdump: ecoffdump.c
|
||||
$(CC) -o ecoffdump ecoffdump.c
|
||||
|
||||
coffdump: coffdump.c
|
||||
$(CC) -o coffdump coffdump.c -lld
|
||||
|
||||
test-dld: test-dld.c
|
||||
$(CC) -o test-dld test-dld.c
|
||||
|
||||
dld: dld.c
|
||||
$(CC) -o dld dld.c -lld
|
||||
|
||||
try: try.c
|
||||
$(CC) -o try try.c -D${MACHINE}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
|
||||
/* Dump ECOFF-MIPS file */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <syms.h>
|
||||
#include <reloc.h>
|
||||
#include <storclass.h>
|
||||
|
||||
filecpy(FILE *to, FILE *from, register int n)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
while (n > BUFSIZ) {
|
||||
fread(buffer, BUFSIZ, 1, from);
|
||||
fwrite(buffer, BUFSIZ, 1, to);
|
||||
n -= BUFSIZ;
|
||||
}
|
||||
if (n > 0) {
|
||||
fread(buffer, 1, n, from);
|
||||
fwrite(buffer, 1, n, to);
|
||||
}
|
||||
}
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, n;
|
||||
FILE *fp, *out;
|
||||
|
||||
FILHDR fileheader;
|
||||
AOUTHDR unix_header;
|
||||
char buf[512];
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
out = fopen(argv[2], "w");
|
||||
|
||||
fread((char *)&fileheader, sizeof(FILHDR), 1, fp);
|
||||
fwrite((char *)&fileheader, sizeof(FILHDR), 1, out);
|
||||
printf("ptr: %d\n", ftell(fp));
|
||||
|
||||
fread(&unix_header, sizeof(AOUTHDR), 1, fp);
|
||||
fwrite(&unix_header, sizeof(AOUTHDR), 1, out);
|
||||
printf("ptr: %d\n", ftell(fp));
|
||||
/*
|
||||
for (i = 0; i < fileheader.f_nscns; i++) {
|
||||
fread(§ion[i], sizeof(SCNHDR), 1, fp);
|
||||
fwrite(§ion[i], sizeof(SCNHDR), 1, out);
|
||||
}
|
||||
*/
|
||||
printf("symptr: %d, ptr: %d\n", fileheader.f_symptr, ftell(fp));
|
||||
filecpy(out, fp, fileheader.f_symptr - ftell(fp));
|
||||
while ((n = read(_fileno(fp), buf, sizeof buf)) > 0) {
|
||||
write(_fileno(out), buf, n);
|
||||
printf("in: %d, out: %d\n", ftell(fp), ftell(out));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,272 +0,0 @@
|
|||
|
||||
/* Dump COFF file */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <syms.h>
|
||||
#include <reloc.h>
|
||||
#include <ldfcn.h>
|
||||
|
||||
#ifdef __sgi
|
||||
#define ECOFF
|
||||
#endif
|
||||
|
||||
#ifdef ECOFF
|
||||
#define SYMENT SYMR
|
||||
#define SYM_VALUE(sym) (sym).value
|
||||
#else
|
||||
#define SYM_VALUE(sym) (sym).n_value
|
||||
#endif
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
char *s;
|
||||
char *string_table;
|
||||
|
||||
LDFILE *ldptr;
|
||||
struct aouthdr unix_header;
|
||||
SCNHDR secthead1;
|
||||
SCNHDR secthead2;
|
||||
SCNHDR secthead3;
|
||||
SCNHDR secthead4;
|
||||
SCNHDR sectheadn;
|
||||
SYMENT symbol;
|
||||
struct reloc reloc;
|
||||
|
||||
printf("sizeof(struct reloc) = %d\n\n", sizeof(struct reloc));
|
||||
printf("sizeof(SYMENT) = %d\n\n", sizeof(SYMENT));
|
||||
|
||||
ldptr = ldopen(argv[1], NULL);
|
||||
|
||||
printf("f_magic: %o\n", HEADER(ldptr).f_magic);
|
||||
printf("f_nscns: %d\n", HEADER(ldptr).f_nscns);
|
||||
printf("f_timdat: %d\n", HEADER(ldptr).f_timdat);
|
||||
printf("f_symptr: %d\n", HEADER(ldptr).f_symptr);
|
||||
printf("f_nsyms: %d\n", HEADER(ldptr).f_nsyms);
|
||||
printf("f_opthdr: %d\n", HEADER(ldptr).f_opthdr);
|
||||
printf("f_flags: %o\n", HEADER(ldptr).f_flags);
|
||||
|
||||
if(HEADER(ldptr).f_opthdr) {
|
||||
|
||||
FSEEK(ldptr, sizeof(struct filehdr), 0);
|
||||
FREAD((char *)&unix_header, sizeof(struct aouthdr), 1, ldptr);
|
||||
|
||||
#ifdef apollo
|
||||
printf("\nvformat: %o\n", unix_header.vformat);
|
||||
#else
|
||||
printf("\nmagic: %o\n", unix_header.magic);
|
||||
#endif /* apollo */
|
||||
printf("vstamp: %o\n", unix_header.vstamp);
|
||||
printf("tsize: %d\n", unix_header.tsize);
|
||||
printf("dsize: %d\n", unix_header.dsize);
|
||||
printf("bsize: %d\n", unix_header.bsize);
|
||||
printf("entry: %d\n", unix_header.entry);
|
||||
printf("text_start: %d\n", unix_header.text_start);
|
||||
printf("data_start: %d\n", unix_header.data_start);
|
||||
#ifdef apollo
|
||||
printf("o_sri: %d\n", unix_header.o_sri);
|
||||
printf("o_inlib: %d\n", unix_header.o_inlib);
|
||||
printf("vid[0]: %d, vid[1]: %d\n", unix_header.vid[0], unix_header.vid[1]);
|
||||
#endif /* apollo */
|
||||
}
|
||||
|
||||
ldshread(ldptr, 1, §head1);
|
||||
|
||||
printf("\nsecthead1:\n");
|
||||
printf("s_name: %s\n", secthead1.s_name);
|
||||
printf("s_paddr: %d\n", secthead1.s_paddr);
|
||||
printf("s_vaddr: %d\n", secthead1.s_vaddr);
|
||||
printf("s_size: %d\n", secthead1.s_size);
|
||||
printf("s_scnptr: %d\n", secthead1.s_scnptr);
|
||||
printf("s_relptr: %d\n", secthead1.s_relptr);
|
||||
printf("s_lnnoptr: %d\n", secthead1.s_lnnoptr);
|
||||
printf("s_nreloc: %d\n", secthead1.s_nreloc);
|
||||
printf("s_nlnno: %d\n", secthead1.s_nlnno);
|
||||
printf("s_flags: %o\n", secthead1.s_flags);
|
||||
|
||||
ldshread(ldptr, 2, §head2);
|
||||
|
||||
printf("\nsecthead2:\n");
|
||||
printf("s_name: %s\n", secthead2.s_name);
|
||||
printf("s_paddr: %d\n", secthead2.s_paddr);
|
||||
printf("s_vaddr: %d\n", secthead2.s_vaddr);
|
||||
printf("s_size: %d\n", secthead2.s_size);
|
||||
printf("s_scnptr: %d\n", secthead2.s_scnptr);
|
||||
printf("s_relptr: %d\n", secthead2.s_relptr);
|
||||
printf("s_lnnoptr: %d\n", secthead2.s_lnnoptr);
|
||||
printf("s_nreloc: %d\n", secthead2.s_nreloc);
|
||||
printf("s_nlnno: %d\n", secthead2.s_nlnno);
|
||||
printf("s_flags: %o\n", secthead2.s_flags);
|
||||
|
||||
ldshread(ldptr, 3, §head3);
|
||||
|
||||
printf("\nsecthead3:\n");
|
||||
printf("s_name: %s\n", secthead3.s_name);
|
||||
printf("s_paddr: %d\n", secthead3.s_paddr);
|
||||
printf("s_vaddr: %d\n", secthead3.s_vaddr);
|
||||
printf("s_size: %d\n", secthead3.s_size);
|
||||
printf("s_scnptr: %d\n", secthead3.s_scnptr);
|
||||
printf("s_relptr: %d\n", secthead3.s_relptr);
|
||||
printf("s_lnnoptr: %d\n", secthead3.s_lnnoptr);
|
||||
printf("s_nreloc: %d\n", secthead3.s_nreloc);
|
||||
printf("s_nlnno: %d\n", secthead3.s_nlnno);
|
||||
printf("s_flags: %o\n", secthead3.s_flags);
|
||||
|
||||
ldshread(ldptr, 4, §head4);
|
||||
|
||||
printf("\nsecthead4:\n");
|
||||
printf("s_name: %s\n", secthead4.s_name);
|
||||
printf("s_paddr: %d\n", secthead4.s_paddr);
|
||||
printf("s_vaddr: %d\n", secthead4.s_vaddr);
|
||||
printf("s_size: %d\n", secthead4.s_size);
|
||||
printf("s_scnptr: %d\n", secthead4.s_scnptr);
|
||||
printf("s_relptr: %d\n", secthead4.s_relptr);
|
||||
printf("s_lnnoptr: %d\n", secthead4.s_lnnoptr);
|
||||
printf("s_nreloc: %d\n", secthead4.s_nreloc);
|
||||
printf("s_nlnno: %d\n", secthead4.s_nlnno);
|
||||
printf("s_flags: %o\n", secthead4.s_flags);
|
||||
|
||||
#ifdef apollo
|
||||
for (i = 5; i <= HEADER(ldptr).f_nscns; i++) {
|
||||
ldshread(ldptr, i, §headn);
|
||||
|
||||
printf("\nsectheadn:\n");
|
||||
printf("s_name: %s\n", sectheadn.s_name);
|
||||
printf("s_paddr: %d\n", sectheadn.s_paddr);
|
||||
printf("s_vaddr: %d\n", sectheadn.s_vaddr);
|
||||
printf("s_size: %d\n", sectheadn.s_size);
|
||||
printf("s_scnptr: %d\n", sectheadn.s_scnptr);
|
||||
printf("s_relptr: %d\n", sectheadn.s_relptr);
|
||||
printf("s_lnnoptr: %d\n", sectheadn.s_lnnoptr);
|
||||
printf("s_nreloc: %d\n", sectheadn.s_nreloc);
|
||||
printf("s_nlnno: %d\n", sectheadn.s_nlnno);
|
||||
printf("s_flags: %o\n", sectheadn.s_flags);
|
||||
}
|
||||
#endif /* apollo */
|
||||
|
||||
printf("\nreloc info for 1:\n");
|
||||
ldrseek(ldptr, 1);
|
||||
for (i = 0; i < secthead1.s_nreloc; i++) {
|
||||
j = fread(&reloc, 10, 1, IOPTR(ldptr));
|
||||
if (j != 1)
|
||||
fprintf(stderr, "READ ERROR\n");
|
||||
printf("\nr_vaddr %d\n", reloc.r_vaddr);
|
||||
printf("r_symndx %d\n", reloc.r_symndx);
|
||||
switch (reloc.r_type) {
|
||||
case R_ABS:
|
||||
printf("r_type R_ABS\n");
|
||||
break;
|
||||
case R_DIR32:
|
||||
printf("r_type R_DIR32\n");
|
||||
break;
|
||||
case R_OFF16:
|
||||
printf("r_type R_OFF16\n");
|
||||
break;
|
||||
case R_DIR32S:
|
||||
printf("r_type R_DIR32S\n");
|
||||
break;
|
||||
case R_REL24:
|
||||
printf("r_type R_REL24\n");
|
||||
break;
|
||||
case R_OPT16:
|
||||
printf("r_type R_OPT16\n");
|
||||
break;
|
||||
case R_IND24:
|
||||
printf("r_type R_IND24\n");
|
||||
break;
|
||||
case R_IND32:
|
||||
printf("r_type R_IND32\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal r_type: %o\n",
|
||||
reloc.r_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nreloc info for 2:\n");
|
||||
ldrseek(ldptr, 2);
|
||||
for (i = 0; i < secthead2.s_nreloc; i++) {
|
||||
fread(&reloc, sizeof(struct reloc), 1, IOPTR(ldptr));
|
||||
printf("\nr_vaddr %d\n", reloc.r_vaddr);
|
||||
printf("r_symndx %d\n", reloc.r_symndx);
|
||||
switch (reloc.r_type) {
|
||||
case R_RELBYTE:
|
||||
printf("r_type R_RELTYPE\n");
|
||||
break;
|
||||
case R_RELWORD:
|
||||
printf("r_type R_RELWORD\n");
|
||||
break;
|
||||
case R_RELLONG:
|
||||
printf("r_type R_RELLONG\n");
|
||||
break;
|
||||
case R_PCRBYTE:
|
||||
printf("r_type R_PCRTYPE\n");
|
||||
break;
|
||||
case R_PCRWORD:
|
||||
printf("r_type R_PCRWORD\n");
|
||||
break;
|
||||
case R_PCRLONG:
|
||||
printf("r_type R_PCRLONG\n");
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Illegal r_type: %d",
|
||||
reloc.r_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
If the string table is not empty,
|
||||
its length is stored after the symbol table,
|
||||
This is not described in the manual, and may change in the future.
|
||||
*/
|
||||
FSEEK(ldptr, STROFFSET(ldptr), 0);
|
||||
if (FREAD((char *)&i, 4, 1, ldptr) > 0) {
|
||||
printf("i: %d\n", i);
|
||||
string_table = (char *)malloc(i);
|
||||
FREAD(string_table, 1, i - 4, ldptr);
|
||||
}
|
||||
|
||||
printf("\nsymbols:\n");
|
||||
for (i = 0; i < HEADER(ldptr).f_nsyms; i++) {
|
||||
ldtbread(ldptr, i, &symbol);
|
||||
printf("\nldgetname(%d): %s\n",
|
||||
i, ldgetname(ldptr, &symbol));
|
||||
#ifdef ECOFF
|
||||
printf("[%d] v %x st %d sc %d index %x %s\n",
|
||||
i, symbol.value, symbol.st, symbol.sc, symbol.index,
|
||||
string_table[symbol.iss]);
|
||||
#else
|
||||
printf("n_value: %o\n", SYM_VALUE(symbol));
|
||||
switch (symbol.n_scnum) {
|
||||
case N_UNDEF:
|
||||
printf("n_scnum: N_UNDEF\n");
|
||||
break;
|
||||
case N_ABS:
|
||||
printf("n_scnum: N_ABS\n");
|
||||
break;
|
||||
case N_DEBUG:
|
||||
printf("n_scnum: N_DEBUG\n");
|
||||
break;
|
||||
case N_TV:
|
||||
printf("n_scnum: N_TV\n");
|
||||
break;
|
||||
case P_TV:
|
||||
printf("n_scnum: P_TV\n");
|
||||
break;
|
||||
default:
|
||||
printf("n_scnum: %d\n", symbol.n_scnum);
|
||||
break;
|
||||
}
|
||||
printf("n_type: %d\n", symbol.n_type);
|
||||
printf("n_sclass: %d\n", symbol.n_sclass);
|
||||
printf("n_numaux: %d\n", symbol.n_numaux);
|
||||
i += symbol.n_numaux;
|
||||
#endif /* ECOFF */
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,270 +0,0 @@
|
|||
|
||||
/* Dump ECOFF-MIPS file */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <syms.h>
|
||||
#include <reloc.h>
|
||||
#include <storclass.h>
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int i, j;
|
||||
char *s;
|
||||
FILE *fp;
|
||||
|
||||
FILHDR fileheader;
|
||||
AOUTHDR unix_header;
|
||||
SCNHDR section[10];
|
||||
HDRR symheader;
|
||||
char *string_table;
|
||||
|
||||
EXTR symbol;
|
||||
RELOC reloc;
|
||||
|
||||
printf("sizeof(RELOC) = %d\n\n", sizeof(RELOC));
|
||||
printf("sizeof(EXTR) = %d\n\n", sizeof(EXTR));
|
||||
|
||||
/* On MIPS the file headers are present also in the memory
|
||||
at address 0x400000 (start of text) */
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
fread((char *)&fileheader, sizeof(FILHDR), 1, fp);
|
||||
|
||||
printf("f_magic: 0x%x\n", fileheader.f_magic);
|
||||
printf("f_nscns: %d\n", fileheader.f_nscns);
|
||||
printf("f_timdat: %d\n", fileheader.f_timdat);
|
||||
printf("f_symptr: %d\n", fileheader.f_symptr);
|
||||
printf("f_nsyms: %d\n", fileheader.f_nsyms);
|
||||
printf("f_opthdr: %d\n", fileheader.f_opthdr);
|
||||
printf("f_flags: 0x%x\n", fileheader.f_flags);
|
||||
|
||||
if (fileheader.f_opthdr) {
|
||||
|
||||
fread(&unix_header, sizeof(AOUTHDR), 1, fp);
|
||||
|
||||
printf("\nmagic: 0%o\n", unix_header.magic);
|
||||
printf("vstamp: 0%o\n", unix_header.vstamp);
|
||||
printf("tsize: %d\n", unix_header.tsize);
|
||||
printf("dsize: %d\n", unix_header.dsize);
|
||||
printf("bsize: %d\n", unix_header.bsize);
|
||||
printf("entry: %d\n", unix_header.entry);
|
||||
printf("text_start: %d\n", unix_header.text_start);
|
||||
printf("data_start: %d\n", unix_header.data_start);
|
||||
#if __mips
|
||||
printf("bss_start: %d\n", unix_header.bss_start);
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; i < fileheader.f_nscns; i++) {
|
||||
fread(§ion[i], sizeof(SCNHDR), 1, fp);
|
||||
printf("\nsection[%d]:\n", i);
|
||||
printf("s_name: %s\n", section[i].s_name);
|
||||
printf("s_paddr:\t%d\n", section[i].s_paddr);
|
||||
printf("s_vaddr:\t%d\n", section[i].s_vaddr);
|
||||
printf("s_size:\t\t%d\n", section[i].s_size);
|
||||
printf("s_scnptr:\t%d\n", section[i].s_scnptr);
|
||||
printf("s_relptr:\t%d\n", section[i].s_relptr);
|
||||
printf("s_lnnoptr:\t%d\n", section[i].s_lnnoptr);
|
||||
printf("s_nreloc:\t%d\n", section[i].s_nreloc);
|
||||
printf("s_nlnno:\t%d\n", section[i].s_nlnno);
|
||||
printf("s_flags:\t0%o\n", section[i].s_flags);
|
||||
}
|
||||
|
||||
/* Print reloc information */
|
||||
for (j = 0; j < fileheader.f_nscns; j++) {
|
||||
if (section[j].s_nreloc == 0) continue;
|
||||
fseek(fp, section[j].s_relptr, 0);
|
||||
printf("\nreloc info for %s:\n", section[j].s_name);
|
||||
printf("\tr_vaddr r_symndx r_type\n\n");
|
||||
for (i = 0; i < section[j].s_nreloc; i++) {
|
||||
if (fread(&reloc, sizeof(reloc), 1, fp) != 1)
|
||||
fprintf(stderr, "READ ERROR\n");
|
||||
printf("%15x %8d ", reloc.r_vaddr, reloc.r_symndx);
|
||||
switch (reloc.r_type) {
|
||||
case R_ABS:
|
||||
printf("R_ABS\n");
|
||||
break;
|
||||
#ifdef __mips
|
||||
case R_REFHALF:
|
||||
printf("R_REFHALF\n");
|
||||
break;
|
||||
case R_REFWORD:
|
||||
printf("R_REFWORD\n");
|
||||
break;
|
||||
case R_JMPADDR: /* 26-bit jump reference */
|
||||
printf("R_JMPADDR\n");
|
||||
break;
|
||||
case R_REFHI:
|
||||
printf("R_REFHI\n");
|
||||
break;
|
||||
case R_REFLO:
|
||||
printf("R_REFLO\n");
|
||||
break;
|
||||
case R_GPREL:
|
||||
printf("R_GPREL\n");
|
||||
break;
|
||||
case R_LITERAL:
|
||||
printf("R_LITERAL\n");
|
||||
break;
|
||||
case R_REL32:
|
||||
printf("R_REL32\n");
|
||||
break;
|
||||
case R_REFHI_64:
|
||||
printf("R_REFHI_64\n");
|
||||
break;
|
||||
case R_REFLO_64:
|
||||
printf("R_REFLO_64\n");
|
||||
break;
|
||||
case R_REFWORD_64:
|
||||
printf("R_REFWORD_64\n");
|
||||
break;
|
||||
case R_PC16:
|
||||
printf("R_PC16\n");
|
||||
break;
|
||||
#ifdef __osf__
|
||||
case R_RELHI:
|
||||
printf("R_RELHI\n");
|
||||
break;
|
||||
case R_RELLO:
|
||||
printf("R_RELLO\n");
|
||||
break;
|
||||
#endif /* __osf__ */
|
||||
case R_REFSHFT:
|
||||
printf("R_REFSHFT\n");
|
||||
break;
|
||||
case R_REFHI_ADDEND:
|
||||
printf("R_REFHI_ADDEND\n");
|
||||
break;
|
||||
#else
|
||||
case R_DIR16:
|
||||
printf("R_DIR16\n");
|
||||
break;
|
||||
case R_REL16:
|
||||
printf("R_REL16\n");
|
||||
break;
|
||||
case R_IND16:
|
||||
printf("R_IND16\n");
|
||||
break;
|
||||
case R_DIR24:
|
||||
printf("R_DIR24\n");
|
||||
break;
|
||||
case R_REL24:
|
||||
printf("R_REL24\n");
|
||||
break;
|
||||
case R_DIR32:
|
||||
printf("R_DIR32\n");
|
||||
break;
|
||||
case R_OFF8:
|
||||
printf("R_OFF8\n");
|
||||
break;
|
||||
case R_OFF16:
|
||||
printf("R_OFF16\n");
|
||||
break;
|
||||
case R_SEG12:
|
||||
printf("R_SEG12\n");
|
||||
break;
|
||||
case R_DIR32S:
|
||||
printf("R_DIR32S\n");
|
||||
break;
|
||||
case R_AUX:
|
||||
printf("R_AUX\n");
|
||||
break;
|
||||
case R_OPT16:
|
||||
printf("R_OPT16\n");
|
||||
break;
|
||||
case R_IND24:
|
||||
printf("R_IND24\n");
|
||||
break;
|
||||
case R_IND32:
|
||||
printf("R_IND32\n");
|
||||
break;
|
||||
case R_RELBYTE:
|
||||
printf("R_RELBYTE\n");
|
||||
break;
|
||||
case R_RELWORD:
|
||||
printf("R_RELWORD\n");
|
||||
break;
|
||||
case R_RELLONG:
|
||||
printf("R_RELLONG\n");
|
||||
break;
|
||||
case R_PCRBYTE:
|
||||
printf("R_PCRBYTE\n");
|
||||
break;
|
||||
case R_PCRWORD:
|
||||
printf("R_PCRWORD\n");
|
||||
break;
|
||||
case R_PCRLONG:
|
||||
printf("R_PCRLONG\n");
|
||||
break;
|
||||
#endif mips
|
||||
|
||||
default:
|
||||
printf("%d\n", reloc.r_type);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fseek(fp, fileheader.f_symptr, 0);
|
||||
fread(&symheader, sizeof(HDRR), 1, fp);
|
||||
printf("\nSymbolic header, magic number = 0x%x, vstamp = %d:\n",
|
||||
symheader.magic, symheader.vstamp);
|
||||
printf("\tInfo\t\t\tOffset\tNumber\tBytes\n\n");
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "Line numbers",
|
||||
symheader.cbLineOffset, symheader.ilineMax, symheader.cbLine);
|
||||
#define SIZE(x, y) ((y) ? (x)-(y) : 0)
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "Dense numbers",
|
||||
symheader.cbDnOffset, symheader.idnMax,
|
||||
SIZE(symheader.cbPdOffset,symheader.cbDnOffset));
|
||||
printf("\t%s\t%d\t%d\t%d\n", "Procedure Tables",
|
||||
symheader.cbPdOffset, symheader.ipdMax,
|
||||
SIZE(symheader.cbSymOffset,symheader.cbPdOffset));
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "Local Symbols",
|
||||
symheader.cbSymOffset, symheader.isymMax,
|
||||
SIZE((symheader.cbOptOffset ?
|
||||
symheader.cbOptOffset : symheader.cbAuxOffset),
|
||||
symheader.cbSymOffset));
|
||||
printf("\t%s\t%d\t%d\t%d\n", "Optimization Symbols",
|
||||
symheader.cbOptOffset, symheader.ioptMax,
|
||||
SIZE(symheader.cbAuxOffset,symheader.cbOptOffset));
|
||||
printf("\t%s\t%d\t%d\t%d\n", "Auxiliary Symbols",
|
||||
symheader.cbAuxOffset, symheader.iauxMax,
|
||||
SIZE(symheader.cbSsOffset,symheader.cbAuxOffset));
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "Local Strings",
|
||||
symheader.cbSsOffset, symheader.issMax,
|
||||
SIZE(symheader.cbExtOffset,symheader.cbSsOffset));
|
||||
printf("\t%s\t%d\t%d\t%d\n", "External Strings",
|
||||
symheader.cbSsExtOffset, symheader.issExtMax,
|
||||
SIZE(symheader.cbFdOffset,symheader.cbSsExtOffset));
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "File Tables",
|
||||
symheader.cbFdOffset, symheader.ifdMax,
|
||||
SIZE(symheader.cbRfdOffset,symheader.cbFdOffset));
|
||||
printf("\t%s\t\t%d\t%d\t%d\n", "Relative Files",
|
||||
symheader.cbRfdOffset, symheader.crfd,
|
||||
SIZE(symheader.cbExtOffset,symheader.cbRfdOffset));
|
||||
printf("\t%s\t%d\t%d\t%d\n", "External Symbols",
|
||||
symheader.cbExtOffset, symheader.iextMax,
|
||||
sizeof(EXTR)*symheader.iextMax);
|
||||
|
||||
/* Read External Strings */
|
||||
fseek(fp, symheader.cbSsExtOffset, 0);
|
||||
i = symheader.cbFdOffset - symheader.cbSsExtOffset;
|
||||
string_table = (char *)malloc(i);
|
||||
fread(string_table, i, 1, fp);
|
||||
|
||||
printf("\nThere are %d external symbols, starting at %d\n\n",
|
||||
symheader.iextMax, symheader.cbExtOffset);
|
||||
|
||||
fseek(fp, symheader.cbExtOffset, 0);
|
||||
for (i = 0; i < symheader.iextMax; i++) {
|
||||
SYMR sym;
|
||||
fread(&symbol, sizeof(symbol), 1, fp);
|
||||
sym = symbol.asym;
|
||||
printf("[%3d]: value %8x st%4d sc%4d index%6x %s\n",
|
||||
i, sym.value, sym.st, sym.sc, sym.index,
|
||||
string_table + sym.iss);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int a[100];
|
||||
|
||||
main()
|
||||
{
|
||||
printf("Hello.\n");
|
||||
printf("a[10] = %d\n", a[10]);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
#include <stdio.h>
|
||||
|
||||
int a[100];
|
||||
|
||||
extra_lenght_foo()
|
||||
{
|
||||
printf("Hello.\n");
|
||||
printf("a[10] = %d\n", a[10]);
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
.file "o.c"
|
||||
.version "RR-0.07-Beta"
|
||||
.LL0:
|
||||
.data
|
||||
.comm a,400
|
||||
.text
|
||||
.align 4
|
||||
.globl extra_lenght_foo
|
||||
extra_lenght_foo:
|
||||
jmp .L28
|
||||
.L27:
|
||||
/ 7 printf("Hello.\n");
|
||||
.text
|
||||
pushl $.L30
|
||||
call printf
|
||||
addl $4,%esp
|
||||
/ 8 printf("a[10] = %d\n", a[10]);
|
||||
.text
|
||||
pushl a+40
|
||||
pushl $.L31
|
||||
call printf
|
||||
addl $8,%esp
|
||||
/ 9 }
|
||||
.L26:
|
||||
leave
|
||||
ret
|
||||
.L28:
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
jmp .L27
|
||||
/FUNCEND
|
||||
.data
|
||||
.L30:
|
||||
|
||||
.byte 0x48,0x65,0x6c,0x6c,0x6f,0x2e,0x0a,0x00
|
||||
.L31:
|
||||
|
||||
.byte 0x61,0x5b,0x31,0x30,0x5d,0x20,0x3d,0x20,0x25,0x64
|
||||
.byte 0x0a,0x00
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <reloc.h>
|
||||
#include <syms.h>
|
||||
|
||||
int a[100];
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
FILE *fp;
|
||||
struct scnhdr section;
|
||||
int tsize, dsize, bsize, text_start;
|
||||
char *text, *malloc();
|
||||
char command[128];
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
fseek(fp, sizeof(struct filehdr), 0);
|
||||
|
||||
fread(§ion, sizeof(struct scnhdr), 1, fp);
|
||||
tsize = section.s_size;
|
||||
text_start = section.s_scnptr;
|
||||
fread(§ion, sizeof(struct scnhdr), 1, fp);
|
||||
dsize = section.s_size;
|
||||
fread(§ion, sizeof(struct scnhdr), 1, fp);
|
||||
bsize - section.s_size;
|
||||
fclose(fp);
|
||||
|
||||
printf("size: %d+%d+%d = %d\n", tsize, dsize, bsize,
|
||||
tsize + dsize + bsize);
|
||||
|
||||
text = malloc(tsize + dsize + bsize);
|
||||
|
||||
sprintf(command, "ild %s %d %s tmp", argv[0], (int)text, argv[1]);
|
||||
printf("%s\n", command);
|
||||
if (system(command) != 0) {
|
||||
fprintf(stderr, "Can't relocate.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = fopen("tmp", "r");
|
||||
fseek(fp, text_start, 0);
|
||||
fread(text, 1, tsize + dsize, fp);
|
||||
fclose(fp);
|
||||
|
||||
a[10] = 123;
|
||||
|
||||
(*(int (*)())text)();
|
||||
}
|
||||
|
||||
dummy()
|
||||
{
|
||||
printf("What?\n");
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
int initflag = 0;
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
char *data_end;
|
||||
extern char *sbrk();
|
||||
extern unexec();
|
||||
char stdin_buf[BUFSIZ], stdout_buf[BUFSIZ];
|
||||
|
||||
main(argc, argv)
|
||||
int argc; char ** argv;
|
||||
{ char *data_start;
|
||||
if (!initflag) {
|
||||
initflag = 1;
|
||||
printf("brk(0): %d\n", sbrk(0));
|
||||
printf("data begin: %d\n", &initflag);
|
||||
data_start = sbrk(2000);
|
||||
brk(data_start + 500);
|
||||
data_end = sbrk(0);
|
||||
printf("data_start: %d, data_end: %d, sbrk: %d\n",
|
||||
data_start, data_end, sbrk(0));
|
||||
unexec("/tmp/foo", argv[0]);
|
||||
} else {
|
||||
printf ("end: %d, sbrk(0): %d, sbrk(0): %d\n", data_end, sbrk(0), sbrk(0));
|
||||
}
|
||||
}
|
||||
269
src/crs/rsym.c
269
src/crs/rsym.c
|
|
@ -1,269 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 1990, Giuseppe Attardi and William F. Schelter.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
This program reads the external symbols from an object file and
|
||||
writes them out to a file together with their addresses.
|
||||
|
||||
This information is used for dynamic linking of object files.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/file.h>
|
||||
#include "machines.h"
|
||||
#include "objff.h"
|
||||
|
||||
|
||||
static FILHDR fileheader;
|
||||
static SYMENT *symbol_table;
|
||||
static char *string_table;
|
||||
static char *start_address;
|
||||
static int nsyms;
|
||||
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3) {
|
||||
perror("Usage: rsym file outfile");
|
||||
fflush(stdout);
|
||||
exit(1);
|
||||
}
|
||||
get_myself(argv[1]);
|
||||
output_externals(argv[1], argv[2]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#ifdef ELF
|
||||
static int text_index, data_index, bss_index, sbss_index;
|
||||
static SCNHDR *section_headers;
|
||||
static char *section_names;
|
||||
|
||||
get_section_number(char *name)
|
||||
{ int k;
|
||||
for (k = 1; k < fileheader.e_shnum; k++)
|
||||
if (strcmp(§ion_names[section_headers[k].sh_name], name) == 0)
|
||||
return k;
|
||||
fprintf(stderr, "Missing section\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *
|
||||
read_section(FILE *fp, int shndx)
|
||||
{
|
||||
char *sec;
|
||||
|
||||
sec = (char *)malloc(section_headers[shndx].sh_size);
|
||||
fseek(fp, section_headers[shndx].sh_offset, SEEK_SET);
|
||||
fread(sec, section_headers[shndx].sh_size, 1, fp);
|
||||
return sec;
|
||||
}
|
||||
#endif ELF
|
||||
|
||||
get_myself(char *filename)
|
||||
{
|
||||
unsigned int i, string_size;
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen(filename, OPEN_R);
|
||||
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Can't open %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
fread((char *)&fileheader, sizeof(FILHDR), 1, fp);
|
||||
if (N_BADMAG(fileheader)) {
|
||||
#ifdef ELF
|
||||
fprintf(stderr, "Bad ELF magic %s",filename);
|
||||
#else
|
||||
fprintf(stderr, "Bad magic %s",filename);
|
||||
#endif
|
||||
exit(1);
|
||||
}
|
||||
#ifdef ELF
|
||||
{ int symbol_index, symsize;
|
||||
/* Read section headers */
|
||||
section_headers = (void *)malloc(sizeof(SCNHDR)*
|
||||
(1 + fileheader.e_shnum));
|
||||
fseek(fp, fileheader.e_shoff, SEEK_SET);
|
||||
for (i = 0 ; i < fileheader.e_shnum ; i++)
|
||||
fread(§ion_headers[i], fileheader.e_shentsize, 1, fp);
|
||||
|
||||
/* Read the section names */
|
||||
section_names = read_section(fp, fileheader.e_shstrndx);
|
||||
|
||||
/* Read the Symbol Table */
|
||||
symbol_index = get_section_number(".symtab");
|
||||
symsize = section_headers[symbol_index].sh_entsize;
|
||||
nsyms = section_headers[symbol_index].sh_size/symsize;
|
||||
symbol_table = (void *) malloc(sizeof(SYMENT) * nsyms);
|
||||
if (fseek(fp, section_headers[symbol_index].sh_offset, SEEK_SET)) {
|
||||
fprintf(stderr, "seek error");
|
||||
exit(1);
|
||||
}
|
||||
for (i = 0; i < nsyms; i++)
|
||||
fread((char *)&symbol_table[i], symsize, 1, fp);
|
||||
|
||||
/* Read the String Table */
|
||||
string_table = read_section(fp, get_section_number(".strtab"));
|
||||
text_index = get_section_number(".text");
|
||||
bss_index = get_section_number(".bss");
|
||||
data_index = get_section_number(".data");
|
||||
}
|
||||
#else /* !ELF */
|
||||
if (fseek(fp, (int)(N_SYMOFF(fileheader)), 0)) {
|
||||
fprintf(stderr, "seek error");
|
||||
exit(1);
|
||||
}
|
||||
# if defined(ECOFF)
|
||||
{ HDRR symheader;
|
||||
fseek(fp, N_SYMOFF(fileheader), 0);
|
||||
fread(&symheader, sizeof(HDRR), 1, fp);
|
||||
|
||||
/* Read External Strings */
|
||||
fseek(fp, symheader.cbSsExtOffset, 0);
|
||||
i = symheader.cbFdOffset - symheader.cbSsExtOffset;
|
||||
string_table = (char *)malloc(i);
|
||||
fread(string_table, i, 1, fp);
|
||||
|
||||
/* Read External Symbols */
|
||||
nsyms = symheader.iextMax;
|
||||
symbol_table = (SYMENT *)malloc(SYMESZ * nsyms);
|
||||
fseek(fp, symheader.cbExtOffset, 0);
|
||||
for (i = 0; i < nsyms; i++)
|
||||
fread(&symbol_table[i], SYMESZ, 1, fp);
|
||||
}
|
||||
# else /* !ECOFF && !ELF */
|
||||
|
||||
nsyms = NSYMS(fileheader);
|
||||
symbol_table = (SYMENT *)malloc(sizeof(SYMENT) * nsyms);
|
||||
# ifndef hpux
|
||||
|
||||
/* Read Symbol Table */
|
||||
for (i = 0; i < nsyms; i++)
|
||||
/* sizeof(SYMENT) and SYMESZ are not always the same */
|
||||
fread((char *)&symbol_table[i], SYMESZ, 1, fp);
|
||||
|
||||
/* Read the String Table */
|
||||
# ifdef N_STROFF
|
||||
fseek(fp, N_STROFF(fileheader), 0);
|
||||
# endif N_STROFF
|
||||
/* First word is size of table: */
|
||||
if (fread((char *)&string_size, sizeof(int), 1, fp) > 0) {
|
||||
string_table = (char *)malloc(string_size);
|
||||
fseek(fp, -sizeof(int), 1);
|
||||
if (string_size != fread(string_table, 1, string_size, fp)) {
|
||||
perror("rsym could not read bad string table");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
perror("Error: There is no string table \n");
|
||||
exit(1);
|
||||
}
|
||||
# else /* hpux */
|
||||
|
||||
for (i = 0; i < nsyms; i++) {
|
||||
fread((char *)&symbol_table[i], SYMESZ, 1, fp);
|
||||
symbol_table[i].n_un.n_strx = string_size;
|
||||
string_size += symbol_table[i].n_length + 1;
|
||||
fseek(fp, symbol_table[i].n_length, 1);
|
||||
}
|
||||
|
||||
/* Read the String Table */
|
||||
{ char *p;
|
||||
int slen;
|
||||
p = string_table = malloc((unsigned int)string_size);
|
||||
dprintf( string table leng = %d, string_size);
|
||||
fseek(fp, (int)( LESYM_OFFSET(fileheader)), 0);
|
||||
for (i = 0; i < nsyms; i++) {
|
||||
fseek(fp, SYMESZ, 1);
|
||||
slen = symbol_table[i].n_length;
|
||||
fread(p, slen, 1, fp);
|
||||
*((p)+slen) = '\0';
|
||||
p += symbol_table[i].n_length + 1;
|
||||
}
|
||||
}
|
||||
# endif hpux
|
||||
# endif ECOFF
|
||||
#endif ELF
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
output_externals(char *infile, char *outfile)
|
||||
{ FILE *fp, *symout;
|
||||
char *name;
|
||||
struct lsymbol_table tab;
|
||||
SYMENT *p, *end;
|
||||
#ifdef SYMNMLEN
|
||||
char tem[SYMNMLEN+1];
|
||||
tem[SYMNMLEN] = 0;
|
||||
#endif
|
||||
|
||||
tab.n_symbols = 0; tab.tot_leng = 0;
|
||||
symout = fopen(outfile, OPEN_W);
|
||||
if (!symout) { perror(outfile); exit(1);}
|
||||
fseek(symout, sizeof(struct lsymbol_table), 0);
|
||||
end = symbol_table + nsyms;
|
||||
for (p = symbol_table; p < end; p++) {
|
||||
/*
|
||||
Is the following check enough?
|
||||
*/
|
||||
if (EXT_and_TEXT_BSS_DAT(p)) {
|
||||
name = SYM_NAME(p);
|
||||
tab.n_symbols++;
|
||||
fwrite((char *)&SYM_VALUE(*p), sizeof(int), 1, symout);
|
||||
while (tab.tot_leng++, *name)
|
||||
putc(*name++, symout);
|
||||
putc('\0', symout);
|
||||
# ifdef NUM_AUX
|
||||
p = p + NUM_AUX(p);
|
||||
# endif
|
||||
}
|
||||
}
|
||||
#ifdef apollo
|
||||
{ struct scnhdr aptvhdr;
|
||||
struct reloc entry;
|
||||
int i, addr;
|
||||
/* go to the relocation entries for section APTV */
|
||||
fp = fopen(infile, OPEN_R);
|
||||
fseek(fp, FILHSZ + sizeof(struct aouthdr) + 2 * SCNHSZ, 0);
|
||||
fread(&aptvhdr, sizeof(struct scnhdr), 1, fp);
|
||||
fseek(fp, aptvhdr.s_relptr, 0);
|
||||
|
||||
/* Each entry corresponds to an external library symbol.
|
||||
Such relocation entry refers to an element of the APTV vector.
|
||||
Elements in the APTV consist in 6 bytes (2 bytes of JMP instruction,
|
||||
4 bytes of JMP address).
|
||||
The relocation entry contains in r_vaddr the address of these 4 bytes.
|
||||
Therefore the relocation address for the symbol is exactly the
|
||||
address of the APTV element, e.g. the r_vaddr - 2.
|
||||
*/
|
||||
|
||||
for (i = 0; i < aptvhdr.s_nreloc; i++) {
|
||||
fread(&entry, sizeof(entry), 1 ,fp);
|
||||
p = &symbol_table[entry.r_symndx];
|
||||
name = SYM_NAME(p);
|
||||
tab.n_symbols++;
|
||||
addr = entry.r_vaddr - 2;
|
||||
fwrite(&addr, sizeof(int), 1, symout);
|
||||
while (tab.tot_leng++, *name)
|
||||
putc(*name++, symout);
|
||||
putc('\0', symout);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
#endif apollo
|
||||
fseek(symout, 0, 0);
|
||||
fwrite(&tab, sizeof(tab), 1, symout);
|
||||
fclose(symout);
|
||||
}
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
.text
|
||||
.align 4
|
||||
.global __setjmp
|
||||
.proc 04
|
||||
__setjmp:
|
||||
clr [ %o0 ]
|
||||
st %sp, [ %o0 + 4 ]
|
||||
add 8, %o7, %o1
|
||||
st %o1, [ %o0 + 8 ]
|
||||
st %fp, [ %o0 + 0xc ]
|
||||
st %i7, [ %o0 + 0x10 ]
|
||||
retl
|
||||
mov %g0, %o0
|
||||
.align 4
|
||||
.global __longjmp
|
||||
.proc 04
|
||||
__longjmp: ta 3
|
||||
ld [ %o0 + 4 ], %o2
|
||||
ldd [ %o2 ], %l0
|
||||
ldd [ %o2 + 8 ], %l2
|
||||
ldd [ %o2 + 0x10 ], %l4
|
||||
ldd [ %o2 + 0x18 ], %l6
|
||||
ldd [ %o2 + 0x20 ], %i0
|
||||
ldd [ %o2 + 0x28 ], %i2
|
||||
ldd [ %o2 + 0x30 ], %i4
|
||||
ld [ %o0 + 0xc ], %fp
|
||||
mov %o2, %sp
|
||||
ld [ %o0 + 0x10 ], %i7
|
||||
ld [ %o0 + 8 ], %o3
|
||||
tst %o1
|
||||
bne L1
|
||||
sub %o3, 8, %o7
|
||||
mov 1, %o1
|
||||
L1: retl
|
||||
mov %o1, %o0
|
||||
177
src/crs/socket.c
177
src/crs/socket.c
|
|
@ -1,177 +0,0 @@
|
|||
/* socket.c -- socket interface */
|
||||
/*
|
||||
Copyright (c) 1990, Giuseppe Attardi.
|
||||
|
||||
ECoLisp is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Library Public License as published
|
||||
by the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/socket.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
extern int errno;
|
||||
|
||||
/***********************************************************************
|
||||
* Client side
|
||||
**********************************************************************/
|
||||
|
||||
/*
|
||||
* Attempts to connect to server, given host and port. Returns file
|
||||
* descriptor (network socket) or 0 if connection fails.
|
||||
*/
|
||||
int connect_to_server(char *host, int port)
|
||||
{
|
||||
struct sockaddr_in inaddr; /* INET socket address. */
|
||||
struct sockaddr *addr; /* address to connect to */
|
||||
struct hostent *host_ptr;
|
||||
int addrlen; /* length of address */
|
||||
extern char *getenv();
|
||||
extern struct hostent *gethostbyname();
|
||||
int fd; /* Network socket */
|
||||
|
||||
/* Get the statistics on the specified host. */
|
||||
if ((inaddr.sin_addr.s_addr = inet_addr(host)) == -1) {
|
||||
if ((host_ptr = gethostbyname(host)) == NULL) {
|
||||
/* No such host! */
|
||||
errno = EINVAL;
|
||||
return(0);
|
||||
}
|
||||
/* Check the address type for an internet host. */
|
||||
if (host_ptr->h_addrtype != AF_INET) {
|
||||
/* Not an Internet host! */
|
||||
errno = EPROTOTYPE;
|
||||
return(0);
|
||||
}
|
||||
/* Set up the socket data. */
|
||||
inaddr.sin_family = host_ptr->h_addrtype;
|
||||
memcpy((char *)&inaddr.sin_addr, (char *)host_ptr->h_addr,
|
||||
sizeof(inaddr.sin_addr));
|
||||
}
|
||||
else
|
||||
inaddr.sin_family = AF_INET;
|
||||
|
||||
addr = (struct sockaddr *) &inaddr;
|
||||
addrlen = sizeof (struct sockaddr_in);
|
||||
inaddr.sin_port = port;
|
||||
inaddr.sin_port = htons(inaddr.sin_port);
|
||||
/*
|
||||
* Open the network connection.
|
||||
*/
|
||||
if ((fd = socket((int) addr->sa_family, SOCK_STREAM, 0)) < 0)
|
||||
return(0); /* errno set by system call. */
|
||||
|
||||
#ifdef TCP_NODELAY
|
||||
/* make sure to turn off TCP coalescence */
|
||||
{ int mi;
|
||||
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int));
|
||||
}
|
||||
#endif
|
||||
#ifdef THREADS
|
||||
start_critical_section();
|
||||
#endif
|
||||
if (connect(fd, addr, addrlen) == -1) {
|
||||
(void) close (fd);
|
||||
#ifdef THREADS
|
||||
end_critical_section();
|
||||
#endif
|
||||
return(0); /* errno set by system call. */
|
||||
}
|
||||
/*
|
||||
* Return the id if the connection succeeded.
|
||||
*/
|
||||
return(fd);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* Server side
|
||||
**********************************************************************/
|
||||
/*
|
||||
* Creates a server port. Returns file
|
||||
* descriptor (network socket) or 0 if connection fails.
|
||||
*/
|
||||
|
||||
int
|
||||
create_server_port(int port)
|
||||
{
|
||||
struct sockaddr_in inaddr; /* INET socket address. */
|
||||
struct sockaddr *addr; /* address to connect to */
|
||||
int addrlen; /* length of address */
|
||||
int request, conn; /* Network socket */
|
||||
|
||||
/*
|
||||
* Open the network connection.
|
||||
*/
|
||||
if ((request = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
|
||||
return(0); /* errno set by system call. */
|
||||
}
|
||||
|
||||
#ifdef SO_REUSEADDR
|
||||
/* Necesary to restart the server without a reboot */
|
||||
{
|
||||
int one = 1;
|
||||
setsockopt(request, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int));
|
||||
}
|
||||
#endif /* SO_REUSEADDR */
|
||||
#ifdef TCP_NODELAY
|
||||
/* make sure to turn off TCP coalescence */
|
||||
{ int mi;
|
||||
setsockopt(request, IPPROTO_TCP, TCP_NODELAY, &mi, sizeof (int));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set up the socket data. */
|
||||
memset((char *)&inaddr, 0, sizeof(inaddr));
|
||||
inaddr.sin_family = AF_INET;
|
||||
inaddr.sin_port = htons(port);
|
||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
if (bind(request, (struct sockaddr *)&inaddr, sizeof (inaddr)))
|
||||
FEerror("Binding TCP socket", 0);
|
||||
if (listen(request, 1))
|
||||
FEerror("TCP listening", 0);
|
||||
#ifdef THREADS
|
||||
/* Don't make this file-descriptor non-blocking
|
||||
* just block on it before we attempt to accept from it
|
||||
* Think _hard_ about moving this out of here, into somewhere sane
|
||||
* and creating an 'accepting' stream type, which is bound to a port
|
||||
* on reading returns streams
|
||||
*/
|
||||
{
|
||||
FILE *fp; /* need to use FILE *'s rather than fd... *sigh* */
|
||||
if ((fp = fdopen(request, "r")) == (FILE *)0)
|
||||
printf("fdopen didn't work on accept fd!\n"); fflush(stdout);
|
||||
fcntl(request, F_SETFL, O_NONBLOCK);
|
||||
clearerr(fp);
|
||||
|
||||
loop: errno = 0;
|
||||
if ((conn = accept(request, (struct sockaddr *)NULL, (int *)NULL)) < 0)
|
||||
if (errno) {
|
||||
lwpblockon(active, fp, PD_INPUT);
|
||||
clearerr(fp);
|
||||
goto loop;
|
||||
} else {
|
||||
fclose(fp);
|
||||
FEerror("Accepting requests", 0);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
#else
|
||||
if ((conn = accept(request, (struct sockaddr *)NULL, (int *)NULL)) < 0)
|
||||
FEerror("Accepting requests", 0);
|
||||
#endif /* THREADS */
|
||||
|
||||
return(conn);
|
||||
}
|
||||
|
|
@ -1,871 +0,0 @@
|
|||
/* Modified by Andrew.Vignaux@comp.vuw.ac.nz to get it to work :-) */
|
||||
|
||||
/* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
|
||||
/*
|
||||
* unexec.c - Convert a running program into an a.out file.
|
||||
*
|
||||
* Author: Spencer W. Thomas
|
||||
* Computer Science Dept.
|
||||
* University of Utah
|
||||
* Date: Tue Mar 2 1982
|
||||
* Modified heavily since then.
|
||||
*
|
||||
* Synopsis:
|
||||
* unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
* char *new_name, *a_name;
|
||||
* unsigned data_start, bss_start, entry_address;
|
||||
*
|
||||
* Takes a snapshot of the program and makes an a.out format file in the
|
||||
* file named by the string argument new_name.
|
||||
* If a_name is non-NULL, the symbol table will be taken from the given file.
|
||||
* On some machines, an existing a_name file is required.
|
||||
*
|
||||
* The boundaries within the a.out file may be adjusted with the data_start
|
||||
* and bss_start arguments. Either or both may be given as 0 for defaults.
|
||||
*
|
||||
* Data_start gives the boundary between the text segment and the data
|
||||
* segment of the program. The text segment can contain shared, read-only
|
||||
* program code and literal data, while the data segment is always unshared
|
||||
* and unprotected. Data_start gives the lowest unprotected address.
|
||||
* The value you specify may be rounded down to a suitable boundary
|
||||
* as required by the machine you are using.
|
||||
*
|
||||
* Specifying zero for data_start means the boundary between text and data
|
||||
* should not be the same as when the program was loaded.
|
||||
* If NO_REMAP is defined, the argument data_start is ignored and the
|
||||
* segment boundaries are never changed.
|
||||
*
|
||||
* Bss_start indicates how much of the data segment is to be saved in the
|
||||
* a.out file and restored when the program is executed. It gives the lowest
|
||||
* unsaved address, and is rounded up to a page boundary. The default when 0
|
||||
* is given assumes that the entire data segment is to be stored, including
|
||||
* the previous data and bss as well as any additional storage allocated with
|
||||
* break (2).
|
||||
*
|
||||
* The new file is set up to start at entry_address.
|
||||
*
|
||||
* If you make improvements I'd like to get them too.
|
||||
* harpo!utah-cs!thomas, thomas@Utah-20
|
||||
*
|
||||
*/
|
||||
|
||||
/* There are several compilation parameters affecting unexec:
|
||||
|
||||
* COFF
|
||||
|
||||
Define this if your system uses COFF for executables.
|
||||
Otherwise we assume you use Berkeley format.
|
||||
|
||||
* NO_REMAP
|
||||
|
||||
Define this if you do not want to try to save Emacs's pure data areas
|
||||
as part of the text segment.
|
||||
|
||||
Saving them as text is good because it allows users to share more.
|
||||
|
||||
However, on machines that locate the text area far from the data area,
|
||||
the boundary cannot feasibly be moved. Such machines require
|
||||
NO_REMAP.
|
||||
|
||||
Also, remapping can cause trouble with the built-in startup routine
|
||||
/lib/crt0.o, which defines `environ' as an initialized variable.
|
||||
Dumping `environ' as pure does not work! So, to use remapping,
|
||||
you must write a startup routine for your machine in Emacs's crt0.c.
|
||||
If NO_REMAP is defined, Emacs uses the system's crt0.o.
|
||||
|
||||
* SECTION_ALIGNMENT
|
||||
|
||||
Some machines that use COFF executables require that each section
|
||||
start on a certain boundary *in the COFF file*. Such machines should
|
||||
define SECTION_ALIGNMENT to a mask of the low-order bits that must be
|
||||
zero on such a boundary. This mask is used to control padding between
|
||||
segments in the COFF file.
|
||||
|
||||
If SECTION_ALIGNMENT is not defined, the segments are written
|
||||
consecutively with no attempt at alignment. This is right for
|
||||
unmodified system V.
|
||||
|
||||
* SEGMENT_MASK
|
||||
|
||||
Some machines require that the beginnings and ends of segments
|
||||
*in core* be on certain boundaries. For most machines, a page
|
||||
boundary is sufficient. That is the default. When a larger
|
||||
boundary is needed, define SEGMENT_MASK to a mask of
|
||||
the bits that must be zero on such a boundary.
|
||||
|
||||
* A_TEXT_OFFSET(HDR)
|
||||
|
||||
Some machines count the a.out header as part of the size of the text
|
||||
segment (a_text); they may actually load the header into core as the
|
||||
first data in the text segment. Some have additional padding between
|
||||
the header and the real text of the program that is counted in a_text.
|
||||
|
||||
For these machines, define A_TEXT_OFFSET(HDR) to examine the header
|
||||
structure HDR and return the number of bytes to add to `a_text'
|
||||
before writing it (above and beyond the number of bytes of actual
|
||||
program text). HDR's standard fields are already correct, except that
|
||||
this adjustment to the `a_text' field has not yet been made;
|
||||
thus, the amount of offset can depend on the data in the file.
|
||||
|
||||
* A_TEXT_SEEK(HDR)
|
||||
|
||||
If defined, this macro specifies the number of bytes to seek into the
|
||||
a.out file before starting to write the text segment.a
|
||||
|
||||
* EXEC_MAGIC
|
||||
|
||||
For machines using COFF, this macro, if defined, is a value stored
|
||||
into the magic number field of the output file.
|
||||
|
||||
* ADJUST_EXEC_HEADER
|
||||
|
||||
This macro can be used to generate statements to adjust or
|
||||
initialize nonstandard fields in the file header
|
||||
|
||||
* ADDR_CORRECT(ADDR)
|
||||
|
||||
Macro to correct an int which is the bit pattern of a pointer to a byte
|
||||
into an int which is the number of a byte.
|
||||
|
||||
This macro has a default definition which is usually right.
|
||||
This default definition is a no-op on most machines (where a
|
||||
pointer looks like an int) but not on all machines.
|
||||
|
||||
*/
|
||||
|
||||
#define XCOFF
|
||||
#define COFF
|
||||
#define NO_REMAP
|
||||
|
||||
#ifndef emacs
|
||||
#define PERROR(arg) perror (arg); return -1
|
||||
#else
|
||||
#include <config.h>
|
||||
#define PERROR(file) report_error (file, new)
|
||||
#endif
|
||||
|
||||
#ifndef CANNOT_DUMP /* all rest of file! */
|
||||
|
||||
#ifndef CANNOT_UNEXEC /* most of rest of file */
|
||||
|
||||
#include <a.out.h>
|
||||
/* Define getpagesize () if the system does not.
|
||||
Note that this may depend on symbols defined in a.out.h
|
||||
*/
|
||||
#include "getpagesize.h"
|
||||
|
||||
#ifndef makedev /* Try to detect types.h already loaded */
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern char *start_of_text (); /* Start of text */
|
||||
extern char *start_of_data (); /* Start of initialized data */
|
||||
|
||||
extern int _data;
|
||||
extern int _edata;
|
||||
extern int _text;
|
||||
extern int _etext;
|
||||
extern int _end;
|
||||
#ifdef COFF
|
||||
#ifndef USG
|
||||
#ifndef STRIDE
|
||||
#ifndef UMAX
|
||||
#ifndef sun386
|
||||
/* I have a suspicion that these are turned off on all systems
|
||||
and can be deleted. Try it in version 19. */
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <syms.h>
|
||||
#endif /* not sun386 */
|
||||
#endif /* not UMAX */
|
||||
#endif /* Not STRIDE */
|
||||
#endif /* not USG */
|
||||
static long block_copy_start; /* Old executable start point */
|
||||
static struct filehdr f_hdr; /* File header */
|
||||
static struct aouthdr f_ohdr; /* Optional file header (a.out) */
|
||||
long bias; /* Bias to add for growth */
|
||||
long lnnoptr; /* Pointer to line-number info within file */
|
||||
#define SYMS_START block_copy_start
|
||||
|
||||
static long text_scnptr;
|
||||
static long data_scnptr;
|
||||
#ifdef XCOFF
|
||||
static long load_scnptr;
|
||||
static long orig_load_scnptr;
|
||||
static long orig_data_scnptr;
|
||||
#endif
|
||||
static long data_st;
|
||||
|
||||
#ifndef MAX_SECTIONS
|
||||
#define MAX_SECTIONS 10
|
||||
#endif
|
||||
|
||||
#endif /* COFF */
|
||||
|
||||
static int pagemask;
|
||||
|
||||
/* Correct an int which is the bit pattern of a pointer to a byte
|
||||
into an int which is the number of a byte.
|
||||
This is a no-op on ordinary machines, but not on all. */
|
||||
|
||||
#ifndef ADDR_CORRECT /* Let m-*.h files override this definition */
|
||||
#define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
|
||||
#endif
|
||||
|
||||
#ifdef emacs
|
||||
|
||||
static
|
||||
report_error (file, fd)
|
||||
char *file;
|
||||
int fd;
|
||||
{
|
||||
if (fd)
|
||||
close (fd);
|
||||
error ("Failure operating on %s", file);
|
||||
}
|
||||
#endif /* emacs */
|
||||
|
||||
#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
|
||||
#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
|
||||
#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
|
||||
|
||||
static
|
||||
report_error_1 (fd, msg, a1, a2)
|
||||
int fd;
|
||||
char *msg;
|
||||
int a1, a2;
|
||||
{
|
||||
close (fd);
|
||||
#ifdef emacs
|
||||
error (msg, a1, a2);
|
||||
#else
|
||||
fprintf (stderr, msg, a1, a2);
|
||||
fprintf (stderr, "\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
static int make_hdr ();
|
||||
static void mark_x ();
|
||||
static int copy_text_and_data ();
|
||||
static int copy_sym ();
|
||||
|
||||
/* ****************************************************************
|
||||
* unexec
|
||||
*
|
||||
* driving logic.
|
||||
*/
|
||||
unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
char *new_name, *a_name;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
{
|
||||
int new, a_out = -1;
|
||||
|
||||
if (a_name && (a_out = open (a_name, 0)) < 0)
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
if ((new = creat (new_name, 0666)) < 0)
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
if (make_hdr (new,a_out,data_start,bss_start,entry_address,a_name,new_name) < 0
|
||||
|| copy_text_and_data (new) < 0
|
||||
|| copy_sym (new, a_out, a_name, new_name) < 0
|
||||
#ifdef COFF
|
||||
|| adjust_lnnoptrs (new, a_out, new_name) < 0
|
||||
#endif
|
||||
#ifdef XCOFF
|
||||
|| unrelocate_symbols (new, a_out, a_name, new_name) < 0
|
||||
#endif
|
||||
)
|
||||
{
|
||||
close (new);
|
||||
/* unlink (new_name); /* Failed, unlink new a.out */
|
||||
return -1;
|
||||
}
|
||||
|
||||
close (new);
|
||||
if (a_out >= 0)
|
||||
close (a_out);
|
||||
mark_x (new_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* make_hdr
|
||||
*
|
||||
* Make the header in the new a.out from the header in core.
|
||||
* Modify the text and data sizes.
|
||||
*/
|
||||
static int
|
||||
make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
|
||||
int new, a_out;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
char *a_name;
|
||||
char *new_name;
|
||||
{
|
||||
register int scns;
|
||||
unsigned int bss_end;
|
||||
|
||||
struct scnhdr section[MAX_SECTIONS];
|
||||
struct scnhdr * f_thdr; /* Text section header */
|
||||
struct scnhdr * f_dhdr; /* Data section header */
|
||||
struct scnhdr * f_bhdr; /* Bss section header */
|
||||
struct scnhdr * f_lhdr; /* Loader section header */
|
||||
struct scnhdr * f_tchdr; /* Typechk section header */
|
||||
struct scnhdr * f_dbhdr; /* Debug section header */
|
||||
struct scnhdr * f_xhdr; /* Except section header */
|
||||
|
||||
load_scnptr = orig_load_scnptr = lnnoptr = 0;
|
||||
pagemask = getpagesize () - 1;
|
||||
|
||||
/* Adjust text/data boundary. */
|
||||
#ifdef NO_REMAP
|
||||
data_start = (long) start_of_data ();
|
||||
#endif /* NO_REMAP */
|
||||
data_start = ADDR_CORRECT (data_start);
|
||||
|
||||
#ifdef SEGMENT_MASK
|
||||
data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */
|
||||
#else
|
||||
data_start = data_start & ~pagemask; /* (Down) to page boundary. */
|
||||
#endif
|
||||
|
||||
|
||||
bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
|
||||
bss_end &= ~ pagemask;
|
||||
/* Adjust data/bss boundary. */
|
||||
if (bss_start != 0)
|
||||
{
|
||||
bss_start = (ADDR_CORRECT (bss_start) + pagemask);
|
||||
/* (Up) to page bdry. */
|
||||
bss_start &= ~ pagemask;
|
||||
if (bss_start > bss_end)
|
||||
{
|
||||
ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
|
||||
bss_start);
|
||||
}
|
||||
}
|
||||
else
|
||||
bss_start = bss_end;
|
||||
|
||||
if (data_start > bss_start) /* Can't have negative data size. */
|
||||
{
|
||||
ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
|
||||
data_start, bss_start);
|
||||
}
|
||||
|
||||
#ifdef COFF
|
||||
/* Salvage as much info from the existing file as possible */
|
||||
block_copy_start = 0;
|
||||
f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
|
||||
f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
|
||||
if (a_out >= 0)
|
||||
{
|
||||
if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
block_copy_start += sizeof (f_hdr);
|
||||
if (f_hdr.f_opthdr > 0)
|
||||
{
|
||||
if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
block_copy_start += sizeof (f_ohdr);
|
||||
}
|
||||
if (f_hdr.f_nscns > MAX_SECTIONS)
|
||||
{
|
||||
ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
|
||||
}
|
||||
/* Loop through section headers */
|
||||
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
|
||||
struct scnhdr *s = §ion[scns];
|
||||
if (read (a_out, s, sizeof (*s)) != sizeof (*s))
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
if (s->s_scnptr > 0L)
|
||||
{
|
||||
if (block_copy_start < s->s_scnptr + s->s_size)
|
||||
block_copy_start = s->s_scnptr + s->s_size;
|
||||
}
|
||||
|
||||
#define CHECK_SCNHDR(ptr, name, flags) \
|
||||
if (strcmp(s->s_name, name) == 0) { \
|
||||
if (s->s_flags != flags) { \
|
||||
fprintf(stderr, "unexec: %x flags where %x expected in %s section.\n", \
|
||||
s->s_flags, flags, name); \
|
||||
} \
|
||||
if (ptr) { \
|
||||
fprintf(stderr, "unexec: duplicate section header for section %s.\n", \
|
||||
name); \
|
||||
} \
|
||||
ptr = s; \
|
||||
}
|
||||
CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT);
|
||||
CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA);
|
||||
CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS);
|
||||
CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER);
|
||||
CHECK_SCNHDR(f_dbhdr, _DEBUG, STYP_DEBUG);
|
||||
CHECK_SCNHDR(f_tchdr, _TYPCHK, STYP_TYPCHK);
|
||||
CHECK_SCNHDR(f_xhdr, _EXCEPT, STYP_EXCEPT);
|
||||
}
|
||||
|
||||
if (f_thdr == 0)
|
||||
{
|
||||
ERROR1 ("unexec: couldn't find \"%s\" section", _TEXT);
|
||||
}
|
||||
if (f_dhdr == 0)
|
||||
{
|
||||
ERROR1 ("unexec: couldn't find \"%s\" section", _DATA);
|
||||
}
|
||||
if (f_bhdr == 0)
|
||||
{
|
||||
ERROR1 ("unexec: couldn't find \"%s\" section", _BSS);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR0 ("can't build a COFF file from scratch yet");
|
||||
}
|
||||
orig_data_scnptr = f_dhdr->s_scnptr;
|
||||
orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
|
||||
|
||||
/* Now we alter the contents of all the f_*hdr variables
|
||||
to correspond to what we want to dump. */
|
||||
f_hdr.f_flags |= (F_RELFLG | F_EXEC); /* Why? */
|
||||
#ifdef EXEC_MAGIC
|
||||
f_ohdr.magic = EXEC_MAGIC;
|
||||
#endif
|
||||
#ifndef NO_REMAP
|
||||
f_ohdr.tsize = data_start - f_ohdr.text_start;
|
||||
f_ohdr.text_start = (long) start_of_text ();
|
||||
#endif
|
||||
f_ohdr.dsize = bss_start - ((unsigned) &_data);
|
||||
f_ohdr.bsize = bss_end - bss_start;
|
||||
|
||||
f_dhdr->s_size = f_ohdr.dsize;
|
||||
f_bhdr->s_size = f_ohdr.bsize;
|
||||
f_bhdr->s_paddr = f_ohdr.dsize;
|
||||
f_bhdr->s_vaddr = f_ohdr.dsize;
|
||||
|
||||
/* fix scnptr's */
|
||||
{
|
||||
long ptr;
|
||||
|
||||
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
|
||||
struct scnhdr *s = §ion[scns];
|
||||
if (scns == 0)
|
||||
ptr = s->s_scnptr;
|
||||
|
||||
if (s->s_scnptr != 0)
|
||||
{
|
||||
s->s_scnptr = ptr;
|
||||
}
|
||||
|
||||
if ((s->s_flags & 0xffff) == STYP_PAD)
|
||||
{
|
||||
/*
|
||||
* the text_start should probably be o_algntext but that doesn't
|
||||
* seem to change
|
||||
*/
|
||||
if (f_ohdr.text_start != 0) /* && scns != 0 */
|
||||
{
|
||||
s->s_size = 512 - (s->s_scnptr % 512);
|
||||
if (s->s_size == 512)
|
||||
s->s_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ptr = ptr + s->s_size;
|
||||
}
|
||||
|
||||
bias = ptr - block_copy_start;
|
||||
}
|
||||
|
||||
/* fix other pointers */
|
||||
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
|
||||
struct scnhdr *s = §ion[scns];
|
||||
|
||||
if (s->s_relptr != 0)
|
||||
{
|
||||
s->s_relptr += bias;
|
||||
}
|
||||
if (s->s_lnnoptr != 0)
|
||||
{
|
||||
if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
|
||||
s->s_lnnoptr += bias;
|
||||
}
|
||||
}
|
||||
|
||||
if (f_hdr.f_symptr > 0L)
|
||||
{
|
||||
f_hdr.f_symptr += bias;
|
||||
}
|
||||
|
||||
data_st = data_start;
|
||||
text_scnptr = f_thdr->s_scnptr;
|
||||
data_scnptr = f_dhdr->s_scnptr;
|
||||
load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
|
||||
block_copy_start = orig_load_scnptr;
|
||||
|
||||
#ifdef ADJUST_EXEC_HEADER
|
||||
ADJUST_EXEC_HEADER
|
||||
#endif /* ADJUST_EXEC_HEADER */
|
||||
|
||||
if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
|
||||
if (f_hdr.f_opthdr > 0)
|
||||
{
|
||||
if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
}
|
||||
|
||||
for (scns = 0; scns < f_hdr.f_nscns; scns++) {
|
||||
struct scnhdr *s = §ion[scns];
|
||||
if (write (new, s, sizeof (*s)) != sizeof (*s))
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
#endif /* COFF */
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
|
||||
*
|
||||
* Copy the text and data segments from memory to the new a.out
|
||||
*/
|
||||
static int
|
||||
copy_text_and_data (new)
|
||||
int new;
|
||||
{
|
||||
register char *end;
|
||||
register char *ptr;
|
||||
|
||||
lseek (new, (long) text_scnptr, 0);
|
||||
ptr = start_of_text () + text_scnptr;
|
||||
end = ptr + f_ohdr.tsize;
|
||||
write_segment (new, ptr, end);
|
||||
|
||||
lseek (new, (long) data_scnptr, 0);
|
||||
ptr = (char *) &_data;
|
||||
end = ptr + f_ohdr.dsize;
|
||||
write_segment (new, ptr, end);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
write_segment (new, ptr, end)
|
||||
int new;
|
||||
register char *ptr, *end;
|
||||
{
|
||||
register int i, nwrite, ret;
|
||||
char buf[80];
|
||||
extern int errno;
|
||||
char zeros[128];
|
||||
|
||||
bzero (zeros, sizeof zeros);
|
||||
|
||||
for (i = 0; ptr < end;)
|
||||
{
|
||||
/* distance to next multiple of 128. */
|
||||
nwrite = (((int) ptr + 128) & -128) - (int) ptr;
|
||||
/* But not beyond specified end. */
|
||||
if (nwrite > end - ptr) nwrite = end - ptr;
|
||||
ret = write (new, ptr, nwrite);
|
||||
/* If write gets a page fault, it means we reached
|
||||
a gap between the old text segment and the old data segment.
|
||||
This gap has probably been remapped into part of the text segment.
|
||||
So write zeros for it. */
|
||||
if (ret == -1 && errno == EFAULT)
|
||||
{
|
||||
write (new, zeros, nwrite);
|
||||
}
|
||||
else if (nwrite != ret)
|
||||
{
|
||||
sprintf (buf,
|
||||
"unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
|
||||
ptr, new, nwrite, ret, errno);
|
||||
PERROR (buf);
|
||||
}
|
||||
i += nwrite;
|
||||
ptr += nwrite;
|
||||
}
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* copy_sym
|
||||
*
|
||||
* Copy the relocation information and symbol table from the a.out to the new
|
||||
*/
|
||||
static int
|
||||
copy_sym (new, a_out, a_name, new_name)
|
||||
int new, a_out;
|
||||
char *a_name, *new_name;
|
||||
{
|
||||
char page[1024];
|
||||
int n;
|
||||
|
||||
if (a_out < 0)
|
||||
return 0;
|
||||
|
||||
if (SYMS_START == 0L)
|
||||
return 0;
|
||||
|
||||
if (lnnoptr && lnnoptr < SYMS_START) /* if there is line number info */
|
||||
lseek (a_out, lnnoptr, 0); /* start copying from there */
|
||||
else
|
||||
lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
|
||||
|
||||
while ((n = read (a_out, page, sizeof page)) > 0)
|
||||
{
|
||||
if (write (new, page, n) != n)
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
}
|
||||
if (n < 0)
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* mark_x
|
||||
*
|
||||
* After successfully building the new a.out, mark it executable
|
||||
*/
|
||||
static void
|
||||
mark_x (name)
|
||||
char *name;
|
||||
{
|
||||
struct stat sbuf;
|
||||
int um;
|
||||
int new = 0; /* for PERROR */
|
||||
|
||||
um = umask (777);
|
||||
umask (um);
|
||||
if (stat (name, &sbuf) == -1)
|
||||
{
|
||||
PERROR (name);
|
||||
}
|
||||
sbuf.st_mode |= 0111 & ~um;
|
||||
if (chmod (name, sbuf.st_mode) == -1)
|
||||
PERROR (name);
|
||||
}
|
||||
|
||||
/*
|
||||
* If the COFF file contains a symbol table and a line number section,
|
||||
* then any auxiliary entries that have values for x_lnnoptr must
|
||||
* be adjusted by the amount that the line number section has moved
|
||||
* in the file (bias computed in make_hdr). The #@$%&* designers of
|
||||
* the auxiliary entry structures used the absolute file offsets for
|
||||
* the line number entry rather than an offset from the start of the
|
||||
* line number section!
|
||||
*
|
||||
* When I figure out how to scan through the symbol table and pick out
|
||||
* the auxiliary entries that need adjustment, this routine will
|
||||
* be fixed. As it is now, all such entries are wrong and sdb
|
||||
* will complain. Fred Fish, UniSoft Systems Inc.
|
||||
*/
|
||||
|
||||
#ifdef COFF
|
||||
|
||||
/* This function is probably very slow. Instead of reopening the new
|
||||
file for input and output it should copy from the old to the new
|
||||
using the two descriptors already open (WRITEDESC and READDESC).
|
||||
Instead of reading one small structure at a time it should use
|
||||
a reasonable size buffer. But I don't have time to work on such
|
||||
things, so I am installing it as submitted to me. -- RMS. */
|
||||
|
||||
adjust_lnnoptrs (writedesc, readdesc, new_name)
|
||||
int writedesc;
|
||||
int readdesc;
|
||||
char *new_name;
|
||||
{
|
||||
register int nsyms;
|
||||
register int new;
|
||||
#ifdef amdahl_uts
|
||||
SYMENT symentry;
|
||||
AUXENT auxentry;
|
||||
#else
|
||||
struct syment symentry;
|
||||
union auxent auxentry;
|
||||
#endif
|
||||
|
||||
if (!lnnoptr || !f_hdr.f_symptr)
|
||||
return 0;
|
||||
|
||||
if ((new = open (new_name, 2)) < 0)
|
||||
{
|
||||
PERROR (new_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
lseek (new, f_hdr.f_symptr, 0);
|
||||
for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
|
||||
{
|
||||
read (new, &symentry, SYMESZ);
|
||||
if (symentry.n_numaux)
|
||||
{
|
||||
read (new, &auxentry, AUXESZ);
|
||||
nsyms++;
|
||||
if (ISFCN (symentry.n_type)) {
|
||||
auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
|
||||
lseek (new, -AUXESZ, 1);
|
||||
write (new, &auxentry, AUXESZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
close (new);
|
||||
}
|
||||
|
||||
#endif /* COFF */
|
||||
|
||||
#ifdef XCOFF
|
||||
|
||||
/* It is probably a false economy to optimise this routine (it used to
|
||||
read one LDREL and do do two lseeks per iteration) but the wrath of
|
||||
RMS (see above :-) would be too much to bear */
|
||||
|
||||
unrelocate_symbols (new, a_out, a_name, new_name)
|
||||
int new, a_out;
|
||||
char *a_name, *new_name;
|
||||
{
|
||||
register int i;
|
||||
register int l;
|
||||
register LDREL *ldrel;
|
||||
LDHDR ldhdr;
|
||||
LDREL ldrel_buf [20];
|
||||
ulong t_start = (ulong) &_text;
|
||||
ulong d_start = (ulong) &_data;
|
||||
int * p;
|
||||
int dirty;
|
||||
|
||||
if (load_scnptr == 0)
|
||||
return 0;
|
||||
|
||||
lseek (a_out, orig_load_scnptr, 0);
|
||||
if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
|
||||
#define SYMNDX_TEXT 0
|
||||
#define SYMNDX_DATA 1
|
||||
#define SYMNDX_BSS 2
|
||||
l = 0;
|
||||
for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++)
|
||||
{
|
||||
if (l == 0) {
|
||||
lseek (a_out,
|
||||
orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
|
||||
0);
|
||||
|
||||
l = ldhdr.l_nreloc - i;
|
||||
if (l > sizeof (ldrel_buf) / LDRELSZ)
|
||||
l = sizeof (ldrel_buf) / LDRELSZ;
|
||||
|
||||
if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ)
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
ldrel = ldrel_buf;
|
||||
}
|
||||
dirty = 0;
|
||||
|
||||
/* this code may not be necessary */
|
||||
/* I originally had == in the "assignment" and it still unrelocated */
|
||||
|
||||
/* move the BSS loader symbols to the DATA segment */
|
||||
if (ldrel->l_rsecnm == f_ohdr.o_snbss)
|
||||
ldrel->l_rsecnm = f_ohdr.o_sndata, dirty++;
|
||||
|
||||
if (ldrel->l_symndx == SYMNDX_BSS)
|
||||
ldrel->l_symndx = SYMNDX_DATA, dirty++;
|
||||
|
||||
if (dirty)
|
||||
{
|
||||
lseek (new,
|
||||
load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
|
||||
0);
|
||||
|
||||
if (write (new, ldrel, LDRELSZ) != LDRELSZ)
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
}
|
||||
|
||||
if (ldrel->l_rsecnm == f_ohdr.o_sndata)
|
||||
{
|
||||
int orig_int;
|
||||
|
||||
lseek (a_out, orig_data_scnptr + ldrel->l_vaddr, 0);
|
||||
|
||||
if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
|
||||
{
|
||||
PERROR (a_name);
|
||||
}
|
||||
|
||||
switch (ldrel->l_symndx) {
|
||||
case SYMNDX_TEXT:
|
||||
p = (int *) (d_start + ldrel->l_vaddr);
|
||||
orig_int = * p - (t_start - f_ohdr.text_start);
|
||||
break;
|
||||
|
||||
case SYMNDX_DATA:
|
||||
case SYMNDX_BSS:
|
||||
p = (int *) (d_start + ldrel->l_vaddr);
|
||||
orig_int = * p - (d_start - f_ohdr.data_start);
|
||||
break;
|
||||
}
|
||||
|
||||
lseek (new, data_scnptr + ldrel->l_vaddr, 0);
|
||||
if (write (new, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int))
|
||||
{
|
||||
PERROR (new_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* XCOFF */
|
||||
|
||||
#endif /* not CANNOT_UNEXEC */
|
||||
|
||||
#endif /* not CANNOT_DUMP */
|
||||
1055
src/crs/unexec.c
1055
src/crs/unexec.c
File diff suppressed because it is too large
Load diff
|
|
@ -1,781 +0,0 @@
|
|||
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
|
||||
/*
|
||||
* unexec.c - Convert a running program into an a.out file.
|
||||
*
|
||||
* Author: Spencer W. Thomas
|
||||
* Computer Science Dept.
|
||||
* University of Utah
|
||||
* Date: Tue Mar 2 1982
|
||||
* Modified heavily since then.
|
||||
*
|
||||
* Synopsis:
|
||||
* unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
* char *new_name, *a_name;
|
||||
* unsigned data_start, bss_start, entry_address;
|
||||
*
|
||||
* Takes a snapshot of the program and makes an a.out format file in the
|
||||
* file named by the string argument new_name.
|
||||
* If a_name is non-NULL, the symbol table will be taken from the given file.
|
||||
* On some machines, an existing a_name file is required.
|
||||
*
|
||||
* The boundaries within the a.out file may be adjusted with the data_start
|
||||
* and bss_start arguments. Either or both may be given as 0 for defaults.
|
||||
*
|
||||
* Data_start gives the boundary between the text segment and the data
|
||||
* segment of the program. The text segment can contain shared, read-only
|
||||
* program code and literal data, while the data segment is always unshared
|
||||
* and unprotected. Data_start gives the lowest unprotected address.
|
||||
* The value you specify may be rounded down to a suitable boundary
|
||||
* as required by the machine you are using.
|
||||
*
|
||||
* Specifying zero for data_start means the boundary between text and data
|
||||
* should not be the same as when the program was loaded.
|
||||
* If NO_REMAP is defined, the argument data_start is ignored and the
|
||||
* segment boundaries are never changed.
|
||||
*
|
||||
* Bss_start indicates how much of the data segment is to be saved in the
|
||||
* a.out file and restored when the program is executed. It gives the lowest
|
||||
* unsaved address, and is rounded up to a page boundary. The default when 0
|
||||
* is given assumes that the entire data segment is to be stored, including
|
||||
* the previous data and bss as well as any additional storage allocated with
|
||||
* break (2).
|
||||
*
|
||||
* The new file is set up to start at entry_address.
|
||||
*
|
||||
* If you make improvements I'd like to get them too.
|
||||
* harpo!utah-cs!thomas, thomas@Utah-20
|
||||
*
|
||||
*/
|
||||
|
||||
/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
|
||||
* ELF support added.
|
||||
*
|
||||
* Basic theory: the data space of the running process needs to be
|
||||
* dumped to the output file. Normally we would just enlarge the size
|
||||
* of .data, scooting everything down. But we can't do that in ELF,
|
||||
* because there is often something between the .data space and the
|
||||
* .bss space.
|
||||
*
|
||||
* In the temacs dump below, notice that the Global Offset Table
|
||||
* (.got) and the Dynamic link data (.dynamic) come between .data1 and
|
||||
* .bss. It does not work to overlap .data with these fields.
|
||||
*
|
||||
* The solution is to create a new .data segment. This segment is
|
||||
* filled with data from the current process. Since the contents of
|
||||
* various sections refer to sections by index, the new .data segment
|
||||
* is made the last in the table to avoid changing any existing index.
|
||||
|
||||
* This is an example of how the section headers are changed. "Addr"
|
||||
* is a process virtual address. "Offset" is a file offset.
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
|
||||
|
||||
temacs:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 8 3 0x80a98f4 0x608f4 0x449c .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 2 0 0 0x608f4 0x9b90 .symtab
|
||||
18 371 0x4 0x10
|
||||
|
||||
[18] 3 0 0 0x6a484 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[19] 3 0 0 0x729aa 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 1 0 0 0x72a3d 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
|
||||
|
||||
xemacs:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 8 3 0x80c6800 0x7d800 0 .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 2 0 0 0x7d800 0x9b90 .symtab
|
||||
18 371 0x4 0x10
|
||||
|
||||
[18] 3 0 0 0x87390 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[19] 3 0 0 0x8f8b6 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 1 0 0 0x8f949 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
[21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
|
||||
0 0 0x4 0
|
||||
|
||||
* This is an example of how the file header is changed. "Shoff" is
|
||||
* the section header offset within the file. Since that table is
|
||||
* after the new .data section, it is moved. "Shnum" is the number of
|
||||
* sections, which we increment.
|
||||
*
|
||||
* "Phoff" is the file offset to the program header. "Phentsize" and
|
||||
* "Shentsz" are the program and section header entries sizes respectively.
|
||||
* These can be larger than the apparent struct sizes.
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
|
||||
|
||||
temacs:
|
||||
|
||||
**** ELF HEADER ****
|
||||
Class Data Type Machine Version
|
||||
Entry Phoff Shoff Flags Ehsize
|
||||
Phentsize Phnum Shentsz Shnum Shstrndx
|
||||
|
||||
1 1 2 3 1
|
||||
0x80499cc 0x34 0x792f4 0 0x34
|
||||
0x20 5 0x28 21 19
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
|
||||
|
||||
xemacs:
|
||||
|
||||
**** ELF HEADER ****
|
||||
Class Data Type Machine Version
|
||||
Entry Phoff Shoff Flags Ehsize
|
||||
Phentsize Phnum Shentsz Shnum Shstrndx
|
||||
|
||||
1 1 2 3 1
|
||||
0x80499cc 0x34 0x96200 0 0x34
|
||||
0x20 5 0x28 22 19
|
||||
|
||||
* These are the program headers. "Offset" is the file offset to the
|
||||
* segment. "Vaddr" is the memory load address. "Filesz" is the
|
||||
* segment size as it appears in the file, and "Memsz" is the size in
|
||||
* memory. Below, the third segment is the code and the fourth is the
|
||||
* data: the difference between Filesz and Memsz is .bss
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
|
||||
|
||||
temacs:
|
||||
***** PROGRAM EXECUTION HEADER *****
|
||||
Type Offset Vaddr Paddr
|
||||
Filesz Memsz Flags Align
|
||||
|
||||
6 0x34 0x8048034 0
|
||||
0xa0 0xa0 5 0
|
||||
|
||||
3 0xd4 0 0
|
||||
0x13 0 4 0
|
||||
|
||||
1 0x34 0x8048034 0
|
||||
0x3f2f9 0x3f2f9 5 0x1000
|
||||
|
||||
1 0x3f330 0x8088330 0
|
||||
0x215c4 0x25a60 7 0x1000
|
||||
|
||||
2 0x60874 0x80a9874 0
|
||||
0x80 0 7 0
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
|
||||
|
||||
xemacs:
|
||||
***** PROGRAM EXECUTION HEADER *****
|
||||
Type Offset Vaddr Paddr
|
||||
Filesz Memsz Flags Align
|
||||
|
||||
6 0x34 0x8048034 0
|
||||
0xa0 0xa0 5 0
|
||||
|
||||
3 0xd4 0 0
|
||||
0x13 0 4 0
|
||||
|
||||
1 0x34 0x8048034 0
|
||||
0x3f2f9 0x3f2f9 5 0x1000
|
||||
|
||||
1 0x3f330 0x8088330 0
|
||||
0x3e4d0 0x3e4d0 7 0x1000
|
||||
|
||||
2 0x60874 0x80a9874 0
|
||||
0x80 0 7 0
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
|
||||
*
|
||||
* The above mechanism does not work if the unexeced ELF file is being
|
||||
* re-layout by other applications (such as `strip'). All the applications
|
||||
* that re-layout the internal of ELF will layout all sections in ascending
|
||||
* order of their file offsets. After the re-layout, the data2 section will
|
||||
* still be the LAST section in the section header vector, but its file offset
|
||||
* is now being pushed far away down, and causes part of it not to be mapped
|
||||
* in (ie. not covered by the load segment entry in PHDR vector), therefore
|
||||
* causes the new binary to fail.
|
||||
*
|
||||
* The solution is to modify the unexec algorithm to insert the new data2
|
||||
* section header right before the new bss section header, so their file
|
||||
* offsets will be in the ascending order. Since some of the section's (all
|
||||
* sections AFTER the bss section) indexes are now changed, we also need to
|
||||
* modify some fields to make them point to the right sections. This is done
|
||||
* by macro PATCH_INDEX. All the fields that need to be patched are:
|
||||
*
|
||||
* 1. ELF header e_shstrndx field.
|
||||
* 2. section header sh_link and sh_info field.
|
||||
* 3. symbol table entry st_shndx field.
|
||||
*
|
||||
* The above example now should look like:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 8 3 0x80c6800 0x7d800 0 .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[18] 2 0 0 0x7d800 0x9b90 .symtab
|
||||
19 371 0x4 0x10
|
||||
|
||||
[19] 3 0 0 0x87390 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 3 0 0 0x8f8b6 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[21] 1 0 0 0x8f949 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef emacs
|
||||
#define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
|
||||
#else
|
||||
extern void fatal (char *, ...);
|
||||
#endif
|
||||
|
||||
/* Get the address of a particular section or program header entry,
|
||||
* accounting for the size of the entries.
|
||||
*/
|
||||
|
||||
#define OLD_SECTION_H(n) \
|
||||
(*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
|
||||
#define NEW_SECTION_H(n) \
|
||||
(*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
|
||||
#define OLD_PROGRAM_H(n) \
|
||||
(*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
|
||||
#define NEW_PROGRAM_H(n) \
|
||||
(*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
|
||||
|
||||
#define PATCH_INDEX(n) \
|
||||
do { \
|
||||
if ((int) (n) >= old_bss_index) \
|
||||
(n)++; } while (0)
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* Round X up to a multiple of Y. */
|
||||
|
||||
int
|
||||
round_up (x, y)
|
||||
int x, y;
|
||||
{
|
||||
int rem = x % y;
|
||||
if (rem == 0)
|
||||
return x;
|
||||
return x - rem + y;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* unexec
|
||||
*
|
||||
* driving logic.
|
||||
*
|
||||
* In ELF, this works by replacing the old .bss section with a new
|
||||
* .data section, and inserting an empty .bss immediately afterwards.
|
||||
*
|
||||
*/
|
||||
void
|
||||
unexec (new_name, old_name, data_start, bss_start, entry_address)
|
||||
char *new_name, *old_name;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
{
|
||||
extern unsigned int data_end;
|
||||
int new_file, old_file, new_file_size;
|
||||
|
||||
/* Pointers to the base of the image of the two files. */
|
||||
caddr_t old_base, new_base;
|
||||
|
||||
/* Pointers to the file, program and section headers for the old and new
|
||||
* files.
|
||||
*/
|
||||
Elf32_Ehdr *old_file_h, *new_file_h;
|
||||
Elf32_Phdr *old_program_h, *new_program_h;
|
||||
Elf32_Shdr *old_section_h, *new_section_h;
|
||||
|
||||
/* Point to the section name table in the old file */
|
||||
char *old_section_names;
|
||||
|
||||
Elf32_Addr old_bss_addr, new_bss_addr;
|
||||
Elf32_Word old_bss_size, new_data2_size;
|
||||
Elf32_Off new_data2_offset;
|
||||
Elf32_Addr new_data2_addr;
|
||||
|
||||
int n, nn, old_bss_index, old_data_index, new_data2_index;
|
||||
struct stat stat_buf;
|
||||
|
||||
/* Open the old file & map it into the address space. */
|
||||
|
||||
old_file = open (old_name, O_RDONLY);
|
||||
|
||||
if (old_file < 0)
|
||||
fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
|
||||
|
||||
if (fstat (old_file, &stat_buf) == -1)
|
||||
fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
|
||||
|
||||
old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
|
||||
|
||||
if (old_base == (caddr_t) -1)
|
||||
fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size,
|
||||
old_base);
|
||||
#endif
|
||||
|
||||
/* Get pointers to headers & section names */
|
||||
|
||||
old_file_h = (Elf32_Ehdr *) old_base;
|
||||
old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
|
||||
old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
|
||||
old_section_names = (char *) old_base
|
||||
+ OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
|
||||
|
||||
/* Find the old .bss section. Figure out parameters of the new
|
||||
* data2 and bss sections.
|
||||
*/
|
||||
|
||||
for (old_bss_index = 1; old_bss_index < (int) old_file_h->e_shnum;
|
||||
old_bss_index++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Looking for .bss - found %s\n",
|
||||
old_section_names + OLD_SECTION_H (old_bss_index).sh_name);
|
||||
#endif
|
||||
if (!strcmp (old_section_names + OLD_SECTION_H (old_bss_index).sh_name,
|
||||
".bss"))
|
||||
break;
|
||||
}
|
||||
if (old_bss_index == old_file_h->e_shnum)
|
||||
fatal ("Can't find .bss in %s.\n", old_name, 0);
|
||||
|
||||
old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
|
||||
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
|
||||
new_bss_addr = (Elf32_Addr) data_end;
|
||||
new_data2_addr = old_bss_addr;
|
||||
new_data2_size = new_bss_addr - old_bss_addr;
|
||||
new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
|
||||
fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
|
||||
fprintf (stderr, "old_bss_size %x\n", old_bss_size);
|
||||
fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
|
||||
fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
|
||||
fprintf (stderr, "new_data2_size %x\n", new_data2_size);
|
||||
fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
|
||||
#endif
|
||||
|
||||
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
||||
fatal (".bss shrank when undumping???\n", 0, 0);
|
||||
|
||||
/* Set the output file to the right size and mmap it. Set
|
||||
* pointers to various interesting objects. stat_buf still has
|
||||
* old_file data.
|
||||
*/
|
||||
|
||||
new_file = open (new_name, O_RDWR | O_CREAT, 0666);
|
||||
if (new_file < 0)
|
||||
fatal ("Can't creat (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
|
||||
|
||||
if (ftruncate (new_file, new_file_size))
|
||||
fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
new_file, 0);
|
||||
|
||||
if (new_base == (caddr_t) -1)
|
||||
fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_file_h = (Elf32_Ehdr *) new_base;
|
||||
new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
|
||||
new_section_h = (Elf32_Shdr *)
|
||||
((byte *) new_base + old_file_h->e_shoff + new_data2_size);
|
||||
|
||||
/* Make our new file, program and section headers as copies of the
|
||||
* originals.
|
||||
*/
|
||||
|
||||
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
|
||||
memcpy (new_program_h, old_program_h,
|
||||
old_file_h->e_phnum * old_file_h->e_phentsize);
|
||||
|
||||
/* Modify the e_shstrndx if necessary. */
|
||||
PATCH_INDEX (new_file_h->e_shstrndx);
|
||||
|
||||
/* Fix up file header. We'll add one section. Section header is
|
||||
* further away now.
|
||||
*/
|
||||
|
||||
new_file_h->e_shoff += new_data2_size;
|
||||
new_file_h->e_shnum += 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
|
||||
fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
|
||||
fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
|
||||
fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
|
||||
#endif
|
||||
|
||||
/* Fix up a new program header. Extend the writable data segment so
|
||||
* that the bss area is covered too. Find that segment by looking
|
||||
* for a segment that ends just before the .bss area. Make sure
|
||||
* that no segments are above the new .data2. Put a loop at the end
|
||||
* to adjust the offset and address of any segment that is above
|
||||
* data2, just in case we decide to allow this later.
|
||||
*/
|
||||
|
||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||
{
|
||||
/* Compute maximum of all requirements for alignment of section. */
|
||||
int alignment = (NEW_PROGRAM_H (n)).p_align;
|
||||
if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
|
||||
alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
|
||||
|
||||
if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr)
|
||||
fatal ("Program segment above .bss in %s\n", old_name, 0);
|
||||
|
||||
if (NEW_PROGRAM_H (n).p_type == PT_LOAD
|
||||
&& (round_up ((NEW_PROGRAM_H (n)).p_vaddr
|
||||
+ (NEW_PROGRAM_H (n)).p_filesz,
|
||||
alignment)
|
||||
== round_up (old_bss_addr, alignment)))
|
||||
break;
|
||||
}
|
||||
if (n < 0)
|
||||
fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
|
||||
|
||||
NEW_PROGRAM_H (n).p_filesz += new_data2_size;
|
||||
NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
|
||||
|
||||
#if 0 /* Maybe allow section after data2 - does this ever happen? */
|
||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||
{
|
||||
if (NEW_PROGRAM_H (n).p_vaddr
|
||||
&& NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
|
||||
NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
|
||||
|
||||
if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
|
||||
NEW_PROGRAM_H (n).p_offset += new_data2_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fix up section headers based on new .data2 section. Any section
|
||||
* whose offset or virtual address is after the new .data2 section
|
||||
* gets its value adjusted. .bss size becomes zero and new address
|
||||
* is set. data2 section header gets added by copying the existing
|
||||
* .data header and modifying the offset, address and size.
|
||||
*/
|
||||
for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
|
||||
old_data_index++)
|
||||
if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
|
||||
".data"))
|
||||
break;
|
||||
if (old_data_index == old_file_h->e_shnum)
|
||||
fatal ("Can't find .data in %s.\n", old_name, 0);
|
||||
|
||||
/* Walk through all section headers, insert the new data2 section right
|
||||
before the new bss section. */
|
||||
for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
|
||||
{
|
||||
caddr_t src;
|
||||
/* If it is bss section, insert the new data2 section before it. */
|
||||
if (n == old_bss_index)
|
||||
{
|
||||
/* Steal the data section header for this data2 section. */
|
||||
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
|
||||
new_file_h->e_shentsize);
|
||||
|
||||
NEW_SECTION_H (nn).sh_addr = new_data2_addr;
|
||||
NEW_SECTION_H (nn).sh_offset = new_data2_offset;
|
||||
NEW_SECTION_H (nn).sh_size = new_data2_size;
|
||||
/* Use the bss section's alignment. This will assure that the
|
||||
new data2 section always be placed in the same spot as the old
|
||||
bss section by any other application. */
|
||||
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
|
||||
|
||||
/* Now copy over what we have in the memory now. */
|
||||
memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
|
||||
(caddr_t) OLD_SECTION_H (n).sh_addr,
|
||||
new_data2_size);
|
||||
nn++;
|
||||
}
|
||||
|
||||
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
|
||||
old_file_h->e_shentsize);
|
||||
|
||||
/* The new bss section's size is zero, and its file offset and virtual
|
||||
address should be off by NEW_DATA2_SIZE. */
|
||||
if (n == old_bss_index)
|
||||
{
|
||||
/* NN should be `old_bss_index + 1' at this point. */
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||
NEW_SECTION_H (nn).sh_addr += new_data2_size;
|
||||
/* Let the new bss section address alignment be the same as the
|
||||
section address alignment followed the old bss section, so
|
||||
this section will be placed in exactly the same place. */
|
||||
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
|
||||
NEW_SECTION_H (nn).sh_size = 0;
|
||||
}
|
||||
/* Any section that was original placed AFTER the bss section should now
|
||||
be off by NEW_DATA2_SIZE. */
|
||||
else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||
|
||||
/* If any section hdr refers to the section after the new .data
|
||||
section, make it refer to next one because we have inserted
|
||||
a new section in between. */
|
||||
|
||||
PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
|
||||
PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
|
||||
|
||||
/* Now, start to copy the content of sections. */
|
||||
if (NEW_SECTION_H (nn).sh_type == SHT_NULL
|
||||
|| NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
|
||||
continue;
|
||||
|
||||
/* Write out the sections. .data and .data1 (and data2, called
|
||||
* ".data" in the strings table) get copied from the current process
|
||||
* instead of the old file.
|
||||
*/
|
||||
if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
|
||||
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
|
||||
".data1"))
|
||||
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
|
||||
else
|
||||
src = old_base + OLD_SECTION_H (n).sh_offset;
|
||||
|
||||
memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
|
||||
NEW_SECTION_H (nn).sh_size);
|
||||
|
||||
/* If it is the symbol table, its st_shndx field needs to be patched. */
|
||||
if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
|
||||
|| NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
|
||||
{
|
||||
Elf32_Shdr *spt = &NEW_SECTION_H (nn);
|
||||
unsigned int num = spt->sh_size / spt->sh_entsize;
|
||||
Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset +
|
||||
new_base);
|
||||
for (; num--; sym++)
|
||||
{
|
||||
if ((sym->st_shndx == SHN_UNDEF)
|
||||
|| (sym->st_shndx == SHN_ABS)
|
||||
|| (sym->st_shndx == SHN_COMMON))
|
||||
continue;
|
||||
|
||||
PATCH_INDEX (sym->st_shndx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the files and make the new file executable */
|
||||
|
||||
if (close (old_file))
|
||||
fatal ("Can't close (%s): errno %d\n", old_name, errno);
|
||||
|
||||
if (close (new_file))
|
||||
fatal ("Can't close (%s): errno %d\n", new_name, errno);
|
||||
|
||||
if (stat (new_name, &stat_buf) == -1)
|
||||
fatal ("Can't stat (%s): errno %d\n", new_name, errno);
|
||||
|
||||
n = umask (777);
|
||||
umask (n);
|
||||
stat_buf.st_mode |= 0111 & ~n;
|
||||
if (chmod (new_name, stat_buf.st_mode) == -1)
|
||||
fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
|
||||
}
|
||||
|
|
@ -1,854 +0,0 @@
|
|||
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
In other words, you are welcome to use, share and improve this program.
|
||||
You are forbidden to forbid anyone else to use, share and improve
|
||||
what you give them. Help stamp out software-hoarding! */
|
||||
|
||||
|
||||
/*
|
||||
* unexec.c - Convert a running program into an a.out file.
|
||||
*
|
||||
* Author: Spencer W. Thomas
|
||||
* Computer Science Dept.
|
||||
* University of Utah
|
||||
* Date: Tue Mar 2 1982
|
||||
* Modified heavily since then.
|
||||
*
|
||||
* Synopsis:
|
||||
* unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
* char *new_name, *a_name;
|
||||
* unsigned data_start, bss_start, entry_address;
|
||||
*
|
||||
* Takes a snapshot of the program and makes an a.out format file in the
|
||||
* file named by the string argument new_name.
|
||||
* If a_name is non-NULL, the symbol table will be taken from the given file.
|
||||
* On some machines, an existing a_name file is required.
|
||||
*
|
||||
* The boundaries within the a.out file may be adjusted with the data_start
|
||||
* and bss_start arguments. Either or both may be given as 0 for defaults.
|
||||
*
|
||||
* Data_start gives the boundary between the text segment and the data
|
||||
* segment of the program. The text segment can contain shared, read-only
|
||||
* program code and literal data, while the data segment is always unshared
|
||||
* and unprotected. Data_start gives the lowest unprotected address.
|
||||
* The value you specify may be rounded down to a suitable boundary
|
||||
* as required by the machine you are using.
|
||||
*
|
||||
* Specifying zero for data_start means the boundary between text and data
|
||||
* should not be the same as when the program was loaded.
|
||||
* If NO_REMAP is defined, the argument data_start is ignored and the
|
||||
* segment boundaries are never changed.
|
||||
*
|
||||
* Bss_start indicates how much of the data segment is to be saved in the
|
||||
* a.out file and restored when the program is executed. It gives the lowest
|
||||
* unsaved address, and is rounded up to a page boundary. The default when 0
|
||||
* is given assumes that the entire data segment is to be stored, including
|
||||
* the previous data and bss as well as any additional storage allocated with
|
||||
* break (2).
|
||||
*
|
||||
* The new file is set up to start at entry_address.
|
||||
*
|
||||
* If you make improvements I'd like to get them too.
|
||||
* harpo!utah-cs!thomas, thomas@Utah-20
|
||||
*
|
||||
*/
|
||||
|
||||
/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
|
||||
* ELF support added.
|
||||
*
|
||||
* Basic theory: the data space of the running process needs to be
|
||||
* dumped to the output file. Normally we would just enlarge the size
|
||||
* of .data, scooting everything down. But we can't do that in ELF,
|
||||
* because there is often something between the .data space and the
|
||||
* .bss space.
|
||||
*
|
||||
* In the temacs dump below, notice that the Global Offset Table
|
||||
* (.got) and the Dynamic link data (.dynamic) come between .data1 and
|
||||
* .bss. It does not work to overlap .data with these fields.
|
||||
*
|
||||
* The solution is to create a new .data segment. This segment is
|
||||
* filled with data from the current process. Since the contents of
|
||||
* various sections refer to sections by index, the new .data segment
|
||||
* is made the last in the table to avoid changing any existing index.
|
||||
|
||||
* This is an example of how the section headers are changed. "Addr"
|
||||
* is a process virtual address. "Offset" is a file offset.
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
|
||||
|
||||
temacs:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 8 3 0x80a98f4 0x608f4 0x449c .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 2 0 0 0x608f4 0x9b90 .symtab
|
||||
18 371 0x4 0x10
|
||||
|
||||
[18] 3 0 0 0x6a484 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[19] 3 0 0 0x729aa 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 1 0 0 0x72a3d 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
|
||||
|
||||
xemacs:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 8 3 0x80c6800 0x7d800 0 .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 2 0 0 0x7d800 0x9b90 .symtab
|
||||
18 371 0x4 0x10
|
||||
|
||||
[18] 3 0 0 0x87390 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[19] 3 0 0 0x8f8b6 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 1 0 0 0x8f949 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
[21] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
|
||||
0 0 0x4 0
|
||||
|
||||
* This is an example of how the file header is changed. "Shoff" is
|
||||
* the section header offset within the file. Since that table is
|
||||
* after the new .data section, it is moved. "Shnum" is the number of
|
||||
* sections, which we increment.
|
||||
*
|
||||
* "Phoff" is the file offset to the program header. "Phentsize" and
|
||||
* "Shentsz" are the program and section header entries sizes respectively.
|
||||
* These can be larger than the apparent struct sizes.
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
|
||||
|
||||
temacs:
|
||||
|
||||
**** ELF HEADER ****
|
||||
Class Data Type Machine Version
|
||||
Entry Phoff Shoff Flags Ehsize
|
||||
Phentsize Phnum Shentsz Shnum Shstrndx
|
||||
|
||||
1 1 2 3 1
|
||||
0x80499cc 0x34 0x792f4 0 0x34
|
||||
0x20 5 0x28 21 19
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
|
||||
|
||||
xemacs:
|
||||
|
||||
**** ELF HEADER ****
|
||||
Class Data Type Machine Version
|
||||
Entry Phoff Shoff Flags Ehsize
|
||||
Phentsize Phnum Shentsz Shnum Shstrndx
|
||||
|
||||
1 1 2 3 1
|
||||
0x80499cc 0x34 0x96200 0 0x34
|
||||
0x20 5 0x28 22 19
|
||||
|
||||
* These are the program headers. "Offset" is the file offset to the
|
||||
* segment. "Vaddr" is the memory load address. "Filesz" is the
|
||||
* segment size as it appears in the file, and "Memsz" is the size in
|
||||
* memory. Below, the third segment is the code and the fourth is the
|
||||
* data: the difference between Filesz and Memsz is .bss
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
|
||||
|
||||
temacs:
|
||||
***** PROGRAM EXECUTION HEADER *****
|
||||
Type Offset Vaddr Paddr
|
||||
Filesz Memsz Flags Align
|
||||
|
||||
6 0x34 0x8048034 0
|
||||
0xa0 0xa0 5 0
|
||||
|
||||
3 0xd4 0 0
|
||||
0x13 0 4 0
|
||||
|
||||
1 0x34 0x8048034 0
|
||||
0x3f2f9 0x3f2f9 5 0x1000
|
||||
|
||||
1 0x3f330 0x8088330 0
|
||||
0x215c4 0x25a60 7 0x1000
|
||||
|
||||
2 0x60874 0x80a9874 0
|
||||
0x80 0 7 0
|
||||
|
||||
raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
|
||||
|
||||
xemacs:
|
||||
***** PROGRAM EXECUTION HEADER *****
|
||||
Type Offset Vaddr Paddr
|
||||
Filesz Memsz Flags Align
|
||||
|
||||
6 0x34 0x8048034 0
|
||||
0xa0 0xa0 5 0
|
||||
|
||||
3 0xd4 0 0
|
||||
0x13 0 4 0
|
||||
|
||||
1 0x34 0x8048034 0
|
||||
0x3f2f9 0x3f2f9 5 0x1000
|
||||
|
||||
1 0x3f330 0x8088330 0
|
||||
0x3e4d0 0x3e4d0 7 0x1000
|
||||
|
||||
2 0x60874 0x80a9874 0
|
||||
0x80 0 7 0
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
|
||||
*
|
||||
* The above mechanism does not work if the unexeced ELF file is being
|
||||
* re-layout by other applications (such as `strip'). All the applications
|
||||
* that re-layout the internal of ELF will layout all sections in ascending
|
||||
* order of their file offsets. After the re-layout, the data2 section will
|
||||
* still be the LAST section in the section header vector, but its file offset
|
||||
* is now being pushed far away down, and causes part of it not to be mapped
|
||||
* in (ie. not covered by the load segment entry in PHDR vector), therefore
|
||||
* causes the new binary to fail.
|
||||
*
|
||||
* The solution is to modify the unexec algorithm to insert the new data2
|
||||
* section header right before the new bss section header, so their file
|
||||
* offsets will be in the ascending order. Since some of the section's (all
|
||||
* sections AFTER the bss section) indexes are now changed, we also need to
|
||||
* modify some fields to make them point to the right sections. This is done
|
||||
* by macro PATCH_INDEX. All the fields that need to be patched are:
|
||||
*
|
||||
* 1. ELF header e_shstrndx field.
|
||||
* 2. section header sh_link and sh_info field.
|
||||
* 3. symbol table entry st_shndx field.
|
||||
*
|
||||
* The above example now should look like:
|
||||
|
||||
**** SECTION HEADER TABLE ****
|
||||
[No] Type Flags Addr Offset Size Name
|
||||
Link Info Adralgn Entsize
|
||||
|
||||
[1] 1 2 0x80480d4 0xd4 0x13 .interp
|
||||
0 0 0x1 0
|
||||
|
||||
[2] 5 2 0x80480e8 0xe8 0x388 .hash
|
||||
3 0 0x4 0x4
|
||||
|
||||
[3] 11 2 0x8048470 0x470 0x7f0 .dynsym
|
||||
4 1 0x4 0x10
|
||||
|
||||
[4] 3 2 0x8048c60 0xc60 0x3ad .dynstr
|
||||
0 0 0x1 0
|
||||
|
||||
[5] 9 2 0x8049010 0x1010 0x338 .rel.plt
|
||||
3 7 0x4 0x8
|
||||
|
||||
[6] 1 6 0x8049348 0x1348 0x3 .init
|
||||
0 0 0x4 0
|
||||
|
||||
[7] 1 6 0x804934c 0x134c 0x680 .plt
|
||||
0 0 0x4 0x4
|
||||
|
||||
[8] 1 6 0x80499cc 0x19cc 0x3c56f .text
|
||||
0 0 0x4 0
|
||||
|
||||
[9] 1 6 0x8085f3c 0x3df3c 0x3 .fini
|
||||
0 0 0x4 0
|
||||
|
||||
[10] 1 2 0x8085f40 0x3df40 0x69c .rodata
|
||||
0 0 0x4 0
|
||||
|
||||
[11] 1 2 0x80865dc 0x3e5dc 0xd51 .rodata1
|
||||
0 0 0x4 0
|
||||
|
||||
[12] 1 3 0x8088330 0x3f330 0x20afc .data
|
||||
0 0 0x4 0
|
||||
|
||||
[13] 1 3 0x80a8e2c 0x5fe2c 0x89d .data1
|
||||
0 0 0x4 0
|
||||
|
||||
[14] 1 3 0x80a96cc 0x606cc 0x1a8 .got
|
||||
0 0 0x4 0x4
|
||||
|
||||
[15] 6 3 0x80a9874 0x60874 0x80 .dynamic
|
||||
4 0 0x4 0x8
|
||||
|
||||
[16] 1 3 0x80a98f4 0x608f4 0x1cf0c .data
|
||||
0 0 0x4 0
|
||||
|
||||
[17] 8 3 0x80c6800 0x7d800 0 .bss
|
||||
0 0 0x4 0
|
||||
|
||||
[18] 2 0 0 0x7d800 0x9b90 .symtab
|
||||
19 371 0x4 0x10
|
||||
|
||||
[19] 3 0 0 0x87390 0x8526 .strtab
|
||||
0 0 0x1 0
|
||||
|
||||
[20] 3 0 0 0x8f8b6 0x93 .shstrtab
|
||||
0 0 0x1 0
|
||||
|
||||
[21] 1 0 0 0x8f949 0x68b7 .comment
|
||||
0 0 0x1 0
|
||||
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <elf.h>
|
||||
#include <syms.h> /* for HDRR declaration */
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifndef emacs
|
||||
#define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
|
||||
#else
|
||||
extern void fatal(char *, ...);
|
||||
#endif
|
||||
|
||||
/* Get the address of a particular section or program header entry,
|
||||
* accounting for the size of the entries.
|
||||
*/
|
||||
|
||||
#define OLD_SECTION_H(n) \
|
||||
(*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
|
||||
#define NEW_SECTION_H(n) \
|
||||
(*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
|
||||
#define OLD_PROGRAM_H(n) \
|
||||
(*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
|
||||
#define NEW_PROGRAM_H(n) \
|
||||
(*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
|
||||
|
||||
#define PATCH_INDEX(n) \
|
||||
do { \
|
||||
if ((n) >= old_bss_index) \
|
||||
(n)++; } while (0)
|
||||
typedef unsigned char byte;
|
||||
|
||||
/* Round X up to a multiple of Y. */
|
||||
|
||||
int
|
||||
round_up (x, y)
|
||||
int x, y;
|
||||
{
|
||||
int rem = x % y;
|
||||
if (rem == 0)
|
||||
return x;
|
||||
return x - rem + y;
|
||||
}
|
||||
|
||||
/* ****************************************************************
|
||||
* unexec
|
||||
*
|
||||
* driving logic.
|
||||
*
|
||||
* In ELF, this works by replacing the old .bss section with a new
|
||||
* .data section, and inserting an empty .bss immediately afterwards.
|
||||
*
|
||||
*/
|
||||
void
|
||||
unexec (new_name, old_name, data_start, bss_start, entry_address)
|
||||
char *new_name, *old_name;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
{
|
||||
unsigned int bss_end; /* (G. Attardi) */
|
||||
int new_file, old_file, new_file_size;
|
||||
|
||||
/* Pointers to the base of the image of the two files. */
|
||||
caddr_t old_base, new_base;
|
||||
|
||||
/* Pointers to the file, program and section headers for the old and new
|
||||
files. */
|
||||
Elf32_Ehdr *old_file_h, *new_file_h;
|
||||
Elf32_Phdr *old_program_h, *new_program_h;
|
||||
Elf32_Shdr *old_section_h, *new_section_h;
|
||||
|
||||
/* Point to the section name table in the old file. */
|
||||
char *old_section_names;
|
||||
|
||||
Elf32_Addr old_bss_addr, new_bss_addr;
|
||||
Elf32_Word old_bss_size, new_data2_size;
|
||||
Elf32_Off new_data2_offset;
|
||||
Elf32_Addr new_data2_addr;
|
||||
|
||||
int n, nn, old_bss_index, old_data_index, new_data2_index;
|
||||
int old_mdebug_index;
|
||||
struct stat stat_buf;
|
||||
|
||||
/* Open the old file & map it into the address space. */
|
||||
|
||||
old_file = open (old_name, O_RDONLY);
|
||||
|
||||
if (old_file < 0)
|
||||
fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
|
||||
|
||||
if (fstat (old_file, &stat_buf) == -1)
|
||||
fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
|
||||
|
||||
old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
|
||||
|
||||
if (old_base == (caddr_t) -1)
|
||||
fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
|
||||
old_base);
|
||||
#endif
|
||||
|
||||
/* Get pointers to headers & section names. */
|
||||
|
||||
old_file_h = (Elf32_Ehdr *) old_base;
|
||||
old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
|
||||
old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
|
||||
old_section_names
|
||||
= (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
|
||||
|
||||
/* Find the mdebug section, if any. */
|
||||
for (old_mdebug_index = 1; old_mdebug_index < old_file_h->e_shnum; old_mdebug_index++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Looking for .mdebug - found %s\n",
|
||||
old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name);
|
||||
#endif
|
||||
if (!strcmp (old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name,
|
||||
".mdebug"))
|
||||
break;
|
||||
}
|
||||
if (old_mdebug_index == old_file_h->e_shnum)
|
||||
old_mdebug_index = -1; /* just means no such section was present */
|
||||
|
||||
/* Find the old .bss section. Figure out parameters of the new
|
||||
data2 and bss sections. */
|
||||
|
||||
for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Looking for .bss - found %s\n",
|
||||
old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
|
||||
#endif
|
||||
if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
|
||||
".bss"))
|
||||
break;
|
||||
}
|
||||
if (old_bss_index == old_file_h->e_shnum)
|
||||
fatal ("Can't find .bss in %s.\n", old_name, 0);
|
||||
|
||||
old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
|
||||
old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
|
||||
#if defined(emacs) || !defined(DEBUG)
|
||||
bss_end = (unsigned int) sbrk (0);
|
||||
new_bss_addr = (Elf32_Addr) bss_end;
|
||||
#else
|
||||
new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
|
||||
#endif
|
||||
new_data2_addr = old_bss_addr;
|
||||
new_data2_size = new_bss_addr - old_bss_addr;
|
||||
new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "old_bss_index %d\n", old_bss_index);
|
||||
fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
|
||||
fprintf (stderr, "old_bss_size %x\n", old_bss_size);
|
||||
fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
|
||||
fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
|
||||
fprintf (stderr, "new_data2_size %x\n", new_data2_size);
|
||||
fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
|
||||
#endif
|
||||
|
||||
if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
|
||||
fatal (".bss shrank when undumping???\n", 0, 0);
|
||||
|
||||
/* Set the output file to the right size and mmap it. Set
|
||||
pointers to various interesting objects. stat_buf still has
|
||||
old_file data. */
|
||||
|
||||
new_file = open (new_name, O_RDWR | O_CREAT, 0666);
|
||||
if (new_file < 0)
|
||||
fatal ("Can't creat (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
|
||||
|
||||
if (ftruncate (new_file, new_file_size))
|
||||
fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
new_file, 0);
|
||||
|
||||
if (new_base == (caddr_t) -1)
|
||||
fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
|
||||
|
||||
new_file_h = (Elf32_Ehdr *) new_base;
|
||||
new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
|
||||
new_section_h
|
||||
= (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
|
||||
+ new_data2_size);
|
||||
|
||||
/* Make our new file, program and section headers as copies of the
|
||||
originals. */
|
||||
|
||||
memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
|
||||
memcpy (new_program_h, old_program_h,
|
||||
old_file_h->e_phnum * old_file_h->e_phentsize);
|
||||
|
||||
/* Modify the e_shstrndx if necessary. */
|
||||
PATCH_INDEX (new_file_h->e_shstrndx);
|
||||
|
||||
/* Fix up file header. We'll add one section. Section header is
|
||||
further away now. */
|
||||
|
||||
new_file_h->e_shoff += new_data2_size;
|
||||
new_file_h->e_shnum += 1;
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
|
||||
fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
|
||||
fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
|
||||
fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
|
||||
#endif
|
||||
|
||||
/* Fix up a new program header. Extend the writable data segment so
|
||||
that the bss area is covered too. Find that segment by looking
|
||||
for a segment that ends just before the .bss area. Make sure
|
||||
that no segments are above the new .data2. Put a loop at the end
|
||||
to adjust the offset and address of any segment that is above
|
||||
data2, just in case we decide to allow this later. */
|
||||
|
||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||
{
|
||||
/* Compute maximum of all requirements for alignment of section. */
|
||||
int alignment = (NEW_PROGRAM_H (n)).p_align;
|
||||
if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
|
||||
alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
|
||||
|
||||
/* Supposedly this condition is okay for the SGI. */
|
||||
#if 0
|
||||
if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr)
|
||||
fatal ("Program segment above .bss in %s\n", old_name, 0);
|
||||
#endif
|
||||
|
||||
if (NEW_PROGRAM_H (n).p_type == PT_LOAD
|
||||
&& (round_up ((NEW_PROGRAM_H (n)).p_vaddr
|
||||
+ (NEW_PROGRAM_H (n)).p_filesz,
|
||||
alignment)
|
||||
== round_up (old_bss_addr, alignment)))
|
||||
break;
|
||||
}
|
||||
if (n < 0)
|
||||
fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
|
||||
|
||||
NEW_PROGRAM_H (n).p_filesz += new_data2_size;
|
||||
NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
|
||||
|
||||
#if 1 /* Maybe allow section after data2 - does this ever happen? */
|
||||
for (n = new_file_h->e_phnum - 1; n >= 0; n--)
|
||||
{
|
||||
if (NEW_PROGRAM_H (n).p_vaddr
|
||||
&& NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
|
||||
NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
|
||||
|
||||
if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
|
||||
NEW_PROGRAM_H (n).p_offset += new_data2_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Fix up section headers based on new .data2 section. Any section
|
||||
whose offset or virtual address is after the new .data2 section
|
||||
gets its value adjusted. .bss size becomes zero and new address
|
||||
is set. data2 section header gets added by copying the existing
|
||||
.data header and modifying the offset, address and size. */
|
||||
for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
|
||||
old_data_index++)
|
||||
if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
|
||||
".data"))
|
||||
break;
|
||||
if (old_data_index == old_file_h->e_shnum)
|
||||
fatal ("Can't find .data in %s.\n", old_name, 0);
|
||||
|
||||
/* Walk through all section headers, insert the new data2 section right
|
||||
before the new bss section. */
|
||||
for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
|
||||
{
|
||||
caddr_t src;
|
||||
/* If it is bss section, insert the new data2 section before it. */
|
||||
if (n == old_bss_index)
|
||||
{
|
||||
/* Steal the data section header for this data2 section. */
|
||||
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
|
||||
new_file_h->e_shentsize);
|
||||
|
||||
NEW_SECTION_H (nn).sh_addr = new_data2_addr;
|
||||
NEW_SECTION_H (nn).sh_offset = new_data2_offset;
|
||||
NEW_SECTION_H (nn).sh_size = new_data2_size;
|
||||
/* Use the bss section's alignment. This will assure that the
|
||||
new data2 section always be placed in the same spot as the old
|
||||
bss section by any other application. */
|
||||
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
|
||||
|
||||
/* Now copy over what we have in the memory now. */
|
||||
memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
|
||||
(caddr_t) OLD_SECTION_H (n).sh_addr,
|
||||
new_data2_size);
|
||||
nn++;
|
||||
}
|
||||
|
||||
memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
|
||||
old_file_h->e_shentsize);
|
||||
|
||||
/* The new bss section's size is zero, and its file offset and virtual
|
||||
address should be off by NEW_DATA2_SIZE. */
|
||||
if (n == old_bss_index)
|
||||
{
|
||||
/* NN should be `old_bss_index + 1' at this point. */
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||
NEW_SECTION_H (nn).sh_addr += new_data2_size;
|
||||
/* Let the new bss section address alignment be the same as the
|
||||
section address alignment followed the old bss section, so
|
||||
this section will be placed in exactly the same place. */
|
||||
NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
|
||||
NEW_SECTION_H (nn).sh_size = 0;
|
||||
}
|
||||
/* Any section that was original placed AFTER the bss section should now
|
||||
be off by NEW_DATA2_SIZE. */
|
||||
else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
|
||||
NEW_SECTION_H (nn).sh_offset += new_data2_size;
|
||||
|
||||
/* If any section hdr refers to the section after the new .data
|
||||
section, make it refer to next one because we have inserted
|
||||
a new section in between. */
|
||||
|
||||
PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
|
||||
/* For symbol tables, info is a symbol table index,
|
||||
so don't change it. */
|
||||
if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
|
||||
&& NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
|
||||
PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
|
||||
|
||||
/* Now, start to copy the content of sections. */
|
||||
if (NEW_SECTION_H (nn).sh_type == SHT_NULL
|
||||
|| NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
|
||||
continue;
|
||||
|
||||
/* Write out the sections. .data and .data1 (and data2, called
|
||||
".data" in the strings table) get copied from the current process
|
||||
instead of the old file. */
|
||||
if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
|
||||
|| !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
|
||||
".data1"))
|
||||
src = (caddr_t) OLD_SECTION_H (n).sh_addr;
|
||||
else
|
||||
src = old_base + OLD_SECTION_H (n).sh_offset;
|
||||
|
||||
memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
|
||||
NEW_SECTION_H (nn).sh_size);
|
||||
|
||||
/* Adjust the HDRR offsets in .mdebug and copy the
|
||||
line data if it's in its usual 'hole' in the object.
|
||||
Makes the new file debuggable with dbx.
|
||||
patches up two problems: the absolute file offsets
|
||||
in the HDRR record of .mdebug (see /usr/include/syms.h), and
|
||||
the ld bug that gets the line table in a hole in the
|
||||
elf file rather than in the .mdebug section proper.
|
||||
David Anderson. davea@sgi.com Jan 16,1994. */
|
||||
if (n == old_mdebug_index)
|
||||
{
|
||||
#define MDEBUGADJUST(__ct,__fileaddr) \
|
||||
if (n_phdrr->__ct > 0) \
|
||||
{ \
|
||||
n_phdrr->__fileaddr += movement; \
|
||||
}
|
||||
|
||||
HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
|
||||
HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
|
||||
unsigned movement = new_data2_size;
|
||||
|
||||
MDEBUGADJUST (idnMax, cbDnOffset);
|
||||
MDEBUGADJUST (ipdMax, cbPdOffset);
|
||||
MDEBUGADJUST (isymMax, cbSymOffset);
|
||||
MDEBUGADJUST (ioptMax, cbOptOffset);
|
||||
MDEBUGADJUST (iauxMax, cbAuxOffset);
|
||||
MDEBUGADJUST (issMax, cbSsOffset);
|
||||
MDEBUGADJUST (issExtMax, cbSsExtOffset);
|
||||
MDEBUGADJUST (ifdMax, cbFdOffset);
|
||||
MDEBUGADJUST (crfd, cbRfdOffset);
|
||||
MDEBUGADJUST (iextMax, cbExtOffset);
|
||||
/* The Line Section, being possible off in a hole of the object,
|
||||
requires special handling. */
|
||||
if (n_phdrr->cbLine > 0)
|
||||
{
|
||||
if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
|
||||
+ OLD_SECTION_H (n).sh_size))
|
||||
{
|
||||
/* line data is in a hole in elf. do special copy and adjust
|
||||
for this ld mistake.
|
||||
*/
|
||||
n_phdrr->cbLineOffset += movement;
|
||||
|
||||
memcpy (n_phdrr->cbLineOffset + new_base,
|
||||
o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* somehow line data is in .mdebug as it is supposed to be. */
|
||||
MDEBUGADJUST (cbLine, cbLineOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If it is the symbol table, its st_shndx field needs to be patched. */
|
||||
if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
|
||||
|| NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
|
||||
{
|
||||
Elf32_Shdr *spt = &NEW_SECTION_H (nn);
|
||||
unsigned int num = spt->sh_size / spt->sh_entsize;
|
||||
Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset
|
||||
+ new_base);
|
||||
for (; num--; sym++)
|
||||
{
|
||||
if (sym->st_shndx == SHN_UNDEF
|
||||
|| sym->st_shndx == SHN_ABS
|
||||
|| sym->st_shndx == SHN_COMMON)
|
||||
continue;
|
||||
|
||||
PATCH_INDEX (sym->st_shndx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Close the files and make the new file executable. */
|
||||
|
||||
if (close (old_file))
|
||||
fatal ("Can't close (%s): errno %d\n", old_name, errno);
|
||||
|
||||
if (close (new_file))
|
||||
fatal ("Can't close (%s): errno %d\n", new_name, errno);
|
||||
|
||||
if (stat (new_name, &stat_buf) == -1)
|
||||
fatal ("Can't stat (%s): errno %d\n", new_name, errno);
|
||||
|
||||
n = umask (777);
|
||||
umask (n);
|
||||
stat_buf.st_mode |= 0111 & ~n;
|
||||
if (chmod (new_name, stat_buf.st_mode) == -1)
|
||||
fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
/* Unexec for the Alliant FX/2800. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
char *new_name, *a_name;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
{
|
||||
int stat;
|
||||
|
||||
stat = elf_write_modified_data (a_name, new_name);
|
||||
if (stat < 0)
|
||||
perror ("emacs: elf_write_modified_data");
|
||||
else if (stat > 0)
|
||||
fprintf (stderr, "Unspecified error from elf_write_modified_data.\n");
|
||||
}
|
||||
|
|
@ -1,297 +0,0 @@
|
|||
/* Unexec for HP 9000 Series 800 machines.
|
||||
Bob Desinger <hpsemc!bd@hplabs.hp.com>
|
||||
|
||||
Note that the GNU project considers support for HP operation a
|
||||
peripheral activity which should not be allowed to divert effort
|
||||
from development of the GNU system. Changes in this code will be
|
||||
installed when users send them in, but aside from that we don't
|
||||
plan to think about it, or about whether other Emacs maintenance
|
||||
might break it.
|
||||
|
||||
|
||||
Unexec creates a copy of the old a.out file, and replaces the old data
|
||||
area with the current data area. When the new file is executed, the
|
||||
process will see the same data structures and data values that the
|
||||
original process had when unexec was called.
|
||||
|
||||
Unlike other versions of unexec, this one copies symbol table and
|
||||
debug information to the new a.out file. Thus, the new a.out file
|
||||
may be debugged with symbolic debuggers.
|
||||
|
||||
If you fix any bugs in this, I'd like to incorporate your fixes.
|
||||
Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
|
||||
|
||||
CAVEATS:
|
||||
This routine saves the current value of all static and external
|
||||
variables. This means that any data structure that needs to be
|
||||
initialized must be explicitly reset. Variables will not have their
|
||||
expected default values.
|
||||
|
||||
Unfortunately, the HP-UX signal handler has internal initialization
|
||||
flags which are not explicitly reset. Thus, for signals to work in
|
||||
conjunction with this routine, the following code must executed when
|
||||
the new process starts up.
|
||||
|
||||
void _sigreturn();
|
||||
...
|
||||
sigsetreturn(_sigreturn);
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <a.out.h>
|
||||
|
||||
#define NBPG 2048
|
||||
#define roundup(x,n) ( ( (x)+(n-1) ) & ~(n-1) ) /* n is power of 2 */
|
||||
#define min(x,y) ( ((x)<(y))?(x):(y) )
|
||||
|
||||
|
||||
/* Create a new a.out file, same as old but with current data space */
|
||||
|
||||
unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
|
||||
char new_name[]; /* name of the new a.out file to be created */
|
||||
char old_name[]; /* name of the old a.out file */
|
||||
char *new_end_of_text; /* ptr to new edata/etext; NOT USED YET */
|
||||
int dummy1, dummy2; /* not used by emacs */
|
||||
{
|
||||
int old, new;
|
||||
int old_size, new_size;
|
||||
struct header hdr;
|
||||
struct som_exec_auxhdr auxhdr;
|
||||
long i;
|
||||
|
||||
/* For the greatest flexibility, should create a temporary file in
|
||||
the same directory as the new file. When everything is complete,
|
||||
rename the temp file to the new name.
|
||||
This way, a program could update its own a.out file even while
|
||||
it is still executing. If problems occur, everything is still
|
||||
intact. NOT implemented. */
|
||||
|
||||
/* Open the input and output a.out files */
|
||||
old = open(old_name, O_RDONLY);
|
||||
if (old < 0)
|
||||
{ perror(old_name); exit(1); }
|
||||
new = open(new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
|
||||
if (new < 0)
|
||||
{ perror(new_name); exit(1); }
|
||||
|
||||
/* Read the old headers */
|
||||
read_header(old, &hdr, &auxhdr);
|
||||
|
||||
/* Decide how large the new and old data areas are */
|
||||
old_size = auxhdr.exec_dsize;
|
||||
/* I suspect these two statements are separate
|
||||
to avoid a compiler bug in hpux version 8. */
|
||||
i = sbrk (0);
|
||||
new_size = i - auxhdr.exec_dmem;
|
||||
|
||||
/* Copy the old file to the new, up to the data space */
|
||||
lseek(old, 0, 0);
|
||||
copy_file(old, new, auxhdr.exec_dfile);
|
||||
|
||||
/* Skip the old data segment and write a new one */
|
||||
lseek(old, old_size, 1);
|
||||
save_data_space(new, &hdr, &auxhdr, new_size);
|
||||
|
||||
/* Copy the rest of the file */
|
||||
copy_rest(old, new);
|
||||
|
||||
/* Update file pointers since we probably changed size of data area */
|
||||
update_file_ptrs(new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
|
||||
|
||||
/* Save the modified header */
|
||||
write_header(new, &hdr, &auxhdr);
|
||||
|
||||
/* Close the binary file */
|
||||
close(old);
|
||||
close(new);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Save current data space in the file, update header. */
|
||||
|
||||
save_data_space(file, hdr, auxhdr, size)
|
||||
int file;
|
||||
struct header *hdr;
|
||||
struct som_exec_auxhdr *auxhdr;
|
||||
int size;
|
||||
{
|
||||
/* Write the entire data space out to the file */
|
||||
if (write(file, auxhdr->exec_dmem, size) != size)
|
||||
{ perror("Can't save new data space"); exit(1); }
|
||||
|
||||
/* Update the header to reflect the new data size */
|
||||
auxhdr->exec_dsize = size;
|
||||
auxhdr->exec_bsize = 0;
|
||||
}
|
||||
|
||||
/* Update the values of file pointers when something is inserted. */
|
||||
|
||||
update_file_ptrs(file, hdr, auxhdr, location, offset)
|
||||
int file;
|
||||
struct header *hdr;
|
||||
struct som_exec_auxhdr *auxhdr;
|
||||
unsigned int location;
|
||||
int offset;
|
||||
{
|
||||
struct subspace_dictionary_record subspace;
|
||||
int i;
|
||||
|
||||
/* Increase the overall size of the module */
|
||||
hdr->som_length += offset;
|
||||
|
||||
/* Update the various file pointers in the header */
|
||||
#define update(ptr) if (ptr > location) ptr = ptr + offset
|
||||
update(hdr->aux_header_location);
|
||||
update(hdr->space_strings_location);
|
||||
update(hdr->init_array_location);
|
||||
update(hdr->compiler_location);
|
||||
update(hdr->symbol_location);
|
||||
update(hdr->fixup_request_location);
|
||||
update(hdr->symbol_strings_location);
|
||||
update(hdr->unloadable_sp_location);
|
||||
update(auxhdr->exec_tfile);
|
||||
update(auxhdr->exec_dfile);
|
||||
|
||||
/* Do for each subspace dictionary entry */
|
||||
lseek(file, hdr->subspace_location, 0);
|
||||
for (i = 0; i < hdr->subspace_total; i++)
|
||||
{
|
||||
if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace))
|
||||
{ perror("Can't read subspace record"); exit(1); }
|
||||
|
||||
/* If subspace has a file location, update it */
|
||||
if (subspace.initialization_length > 0
|
||||
&& subspace.file_loc_init_value > location)
|
||||
{
|
||||
subspace.file_loc_init_value += offset;
|
||||
lseek(file, -sizeof(subspace), 1);
|
||||
if (write(file, &subspace, sizeof(subspace)) != sizeof(subspace))
|
||||
{ perror("Can't update subspace record"); exit(1); }
|
||||
}
|
||||
}
|
||||
|
||||
/* Do for each initialization pointer record */
|
||||
/* (I don't think it applies to executable files, only relocatables) */
|
||||
#undef update
|
||||
}
|
||||
|
||||
/* Read in the header records from an a.out file. */
|
||||
|
||||
read_header(file, hdr, auxhdr)
|
||||
int file;
|
||||
struct header *hdr;
|
||||
struct som_exec_auxhdr *auxhdr;
|
||||
{
|
||||
|
||||
/* Read the header in */
|
||||
lseek(file, 0, 0);
|
||||
if (read(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
|
||||
{ perror("Couldn't read header from a.out file"); exit(1); }
|
||||
|
||||
if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
|
||||
&& hdr->a_magic != DEMAND_MAGIC)
|
||||
{
|
||||
fprintf(stderr, "a.out file doesn't have legal magic number\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
lseek(file, hdr->aux_header_location, 0);
|
||||
if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
|
||||
{
|
||||
perror("Couldn't read auxiliary header from a.out file");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write out the header records into an a.out file. */
|
||||
|
||||
write_header(file, hdr, auxhdr)
|
||||
int file;
|
||||
struct header *hdr;
|
||||
struct som_exec_auxhdr *auxhdr;
|
||||
{
|
||||
/* Update the checksum */
|
||||
hdr->checksum = calculate_checksum(hdr);
|
||||
|
||||
/* Write the header back into the a.out file */
|
||||
lseek(file, 0, 0);
|
||||
if (write(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
|
||||
{ perror("Couldn't write header to a.out file"); exit(1); }
|
||||
lseek(file, hdr->aux_header_location, 0);
|
||||
if (write(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
|
||||
{ perror("Couldn't write auxiliary header to a.out file"); exit(1); }
|
||||
}
|
||||
|
||||
/* Calculate the checksum of a SOM header record. */
|
||||
|
||||
calculate_checksum(hdr)
|
||||
struct header *hdr;
|
||||
{
|
||||
int checksum, i, *ptr;
|
||||
|
||||
checksum = 0; ptr = (int *) hdr;
|
||||
|
||||
for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++)
|
||||
checksum ^= ptr[i];
|
||||
|
||||
return(checksum);
|
||||
}
|
||||
|
||||
/* Copy size bytes from the old file to the new one. */
|
||||
|
||||
copy_file(old, new, size)
|
||||
int new, old;
|
||||
int size;
|
||||
{
|
||||
int len;
|
||||
int buffer[8196]; /* word aligned will be faster */
|
||||
|
||||
for (; size > 0; size -= len)
|
||||
{
|
||||
len = min(size, sizeof(buffer));
|
||||
if (read(old, buffer, len) != len)
|
||||
{ perror("Read failure on a.out file"); exit(1); }
|
||||
if (write(new, buffer, len) != len)
|
||||
{ perror("Write failure in a.out file"); exit(1); }
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the rest of the file, up to EOF. */
|
||||
|
||||
copy_rest(old, new)
|
||||
int new, old;
|
||||
{
|
||||
int buffer[4096];
|
||||
int len;
|
||||
|
||||
/* Copy bytes until end of file or error */
|
||||
while ( (len = read(old, buffer, sizeof(buffer))) > 0)
|
||||
if (write(new, buffer, len) != len) break;
|
||||
|
||||
if (len != 0)
|
||||
{ perror("Unable to copy the rest of the file"); exit(1); }
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
display_header(hdr, auxhdr)
|
||||
struct header *hdr;
|
||||
struct som_exec_auxhdr *auxhdr;
|
||||
{
|
||||
/* Display the header information (debug) */
|
||||
printf("\n\nFILE HEADER\n");
|
||||
printf("magic number %d \n", hdr->a_magic);
|
||||
printf("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
|
||||
printf("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
|
||||
printf("entry %x \n", auxhdr->exec_entry);
|
||||
printf("Bss segment size %u\n", auxhdr->exec_bsize);
|
||||
printf("\n");
|
||||
printf("data file loc %d size %d\n",
|
||||
auxhdr->exec_dfile, auxhdr->exec_dsize);
|
||||
printf("som_length %d\n", hdr->som_length);
|
||||
printf("unloadable sploc %d size %d\n",
|
||||
hdr->unloadable_sp_location, hdr->unloadable_sp_size);
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
|
@ -1,319 +0,0 @@
|
|||
/* Unexec for MIPS (including IRIS4D).
|
||||
Note that the GNU project considers support for MIPS operation
|
||||
a peripheral activity which should not be allowed to divert effort
|
||||
from development of the GNU system. Changes in this code will be
|
||||
installed when users send them in, but aside from that
|
||||
we don't plan to think about it, or about whether other Emacs
|
||||
maintenance might break it.
|
||||
|
||||
Copyright (C) 1988 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Emacs.
|
||||
|
||||
GNU Emacs is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 1, or (at your option)
|
||||
any later version.
|
||||
|
||||
GNU Emacs is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GNU Emacs; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
/* Modified by G. Attardi (attardi@di.unipi.it), Jan. 1994
|
||||
for using <stdarg.h> instead of <vararg.h> */
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <filehdr.h>
|
||||
#include <aouthdr.h>
|
||||
#include <scnhdr.h>
|
||||
#include <sym.h>
|
||||
|
||||
#if defined (IRIS_4D) || defined (sony)
|
||||
#include "getpagesize.h"
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#define TEXT_START 0x400000
|
||||
|
||||
static void fatal_unexec (char *, ...);
|
||||
static void mark_x ();
|
||||
|
||||
#define READ(_fd, _buffer, _size, _error_message, _error_arg) \
|
||||
errno = EEOF; \
|
||||
if (read (_fd, _buffer, _size) != _size) \
|
||||
fatal_unexec (_error_message, _error_arg);
|
||||
|
||||
#define WRITE(_fd, _buffer, _size, _error_message, _error_arg) \
|
||||
if (write (_fd, _buffer, _size) != _size) \
|
||||
fatal_unexec (_error_message, _error_arg);
|
||||
|
||||
#define SEEK(_fd, _position, _error_message, _error_arg) \
|
||||
errno = EEOF; \
|
||||
if (lseek (_fd, _position, L_SET) != _position) \
|
||||
fatal_unexec (_error_message, _error_arg);
|
||||
|
||||
extern int errno;
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
#define EEOF -1
|
||||
|
||||
static struct scnhdr *text_section;
|
||||
static struct scnhdr *init_section;
|
||||
static struct scnhdr *finit_section;
|
||||
static struct scnhdr *rdata_section;
|
||||
static struct scnhdr *data_section;
|
||||
static struct scnhdr *lit8_section;
|
||||
static struct scnhdr *lit4_section;
|
||||
static struct scnhdr *sdata_section;
|
||||
static struct scnhdr *sbss_section;
|
||||
static struct scnhdr *bss_section;
|
||||
|
||||
struct headers {
|
||||
struct filehdr fhdr;
|
||||
struct aouthdr aout;
|
||||
struct scnhdr section[10];
|
||||
};
|
||||
|
||||
/* Define name of label for entry point for the dumped executable. */
|
||||
|
||||
#ifndef DEFAULT_ENTRY_ADDRESS
|
||||
#define DEFAULT_ENTRY_ADDRESS __start
|
||||
#endif
|
||||
|
||||
unexec (new_name, a_name, data_start, bss_start, entry_address)
|
||||
char *new_name, *a_name;
|
||||
unsigned data_start, bss_start, entry_address;
|
||||
{
|
||||
int new, old;
|
||||
int pagesize, brk;
|
||||
int newsyms, symrel;
|
||||
int nread;
|
||||
struct headers hdr;
|
||||
int i;
|
||||
int vaddr, scnptr;
|
||||
#define BUFSIZE 8192
|
||||
char buffer[BUFSIZE];
|
||||
|
||||
old = open (a_name, O_RDONLY, 0);
|
||||
if (old < 0) fatal_unexec ("opening %s", a_name);
|
||||
|
||||
new = creat (new_name, 0666);
|
||||
if (new < 0) fatal_unexec ("creating %s", new_name);
|
||||
|
||||
hdr = *((struct headers *)TEXT_START);
|
||||
#ifdef MIPS2
|
||||
if (hdr.fhdr.f_magic != MIPSELMAGIC
|
||||
&& hdr.fhdr.f_magic != MIPSEBMAGIC
|
||||
&& hdr.fhdr.f_magic != (MIPSELMAGIC | 1)
|
||||
&& hdr.fhdr.f_magic != (MIPSEBMAGIC | 1))
|
||||
{
|
||||
fprintf (stderr,
|
||||
"unexec: input file magic number is %x, not %x, %x, %x or %x.\n",
|
||||
hdr.fhdr.f_magic,
|
||||
MIPSELMAGIC, MIPSEBMAGIC,
|
||||
MIPSELMAGIC | 1, MIPSEBMAGIC | 1);
|
||||
exit(1);
|
||||
}
|
||||
#else /* not MIPS2 */
|
||||
if (hdr.fhdr.f_magic != MIPSELMAGIC
|
||||
&& hdr.fhdr.f_magic != MIPSEBMAGIC)
|
||||
{
|
||||
fprintf (stderr, "unexec: input file magic number is %x, not %x or %x.\n",
|
||||
hdr.fhdr.f_magic, MIPSELMAGIC, MIPSEBMAGIC);
|
||||
exit (1);
|
||||
}
|
||||
#endif /* not MIPS2 */
|
||||
if (hdr.fhdr.f_opthdr != sizeof (hdr.aout))
|
||||
{
|
||||
fprintf (stderr, "unexec: input a.out header is %d bytes, not %d.\n",
|
||||
hdr.fhdr.f_opthdr, sizeof (hdr.aout));
|
||||
exit (1);
|
||||
}
|
||||
if (hdr.aout.magic != ZMAGIC)
|
||||
{
|
||||
fprintf (stderr, "unexec: input file a.out magic number is %o, not %o.\n",
|
||||
hdr.aout.magic, ZMAGIC);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#define CHECK_SCNHDR(ptr, name, flags) \
|
||||
ptr = NULL; \
|
||||
for (i = 0; i < hdr.fhdr.f_nscns && !ptr; i++) \
|
||||
if (strcmp (hdr.section[i].s_name, name) == 0) \
|
||||
{ \
|
||||
if (hdr.section[i].s_flags != flags) \
|
||||
fprintf (stderr, "unexec: %x flags (%x expected) in %s section.\n", \
|
||||
hdr.section[i].s_flags, flags, name); \
|
||||
ptr = hdr.section + i; \
|
||||
} \
|
||||
|
||||
CHECK_SCNHDR (text_section, _TEXT, STYP_TEXT);
|
||||
CHECK_SCNHDR (init_section, _INIT, STYP_INIT);
|
||||
CHECK_SCNHDR (rdata_section, _RDATA, STYP_RDATA);
|
||||
CHECK_SCNHDR (data_section, _DATA, STYP_DATA);
|
||||
#ifdef _LIT8
|
||||
CHECK_SCNHDR (lit8_section, _LIT8, STYP_LIT8);
|
||||
CHECK_SCNHDR (lit4_section, _LIT4, STYP_LIT4);
|
||||
#endif /* _LIT8 */
|
||||
CHECK_SCNHDR (sdata_section, _SDATA, STYP_SDATA);
|
||||
CHECK_SCNHDR (sbss_section, _SBSS, STYP_SBSS);
|
||||
CHECK_SCNHDR (bss_section, _BSS, STYP_BSS);
|
||||
#if 0 /* Apparently this error check goes off on irix 3.3,
|
||||
but it doesn't indicate a real problem. */
|
||||
if (i != hdr.fhdr.f_nscns)
|
||||
fprintf (stderr, "unexec: %d sections found instead of %d.\n",
|
||||
i, hdr.fhdr.f_nscns);
|
||||
#endif
|
||||
|
||||
text_section->s_scnptr = 0;
|
||||
|
||||
pagesize = getpagesize ();
|
||||
brk = (sbrk (0) + pagesize - 1) & (-pagesize);
|
||||
hdr.aout.dsize = brk - DATA_START;
|
||||
hdr.aout.bsize = 0;
|
||||
if (entry_address == 0)
|
||||
{
|
||||
extern DEFAULT_ENTRY_ADDRESS ();
|
||||
hdr.aout.entry = (unsigned)DEFAULT_ENTRY_ADDRESS;
|
||||
}
|
||||
else
|
||||
hdr.aout.entry = entry_address;
|
||||
|
||||
hdr.aout.bss_start = hdr.aout.data_start + hdr.aout.dsize;
|
||||
rdata_section->s_size = data_start - DATA_START;
|
||||
|
||||
/* Adjust start and virtual addresses of rdata_section, too. */
|
||||
rdata_section->s_vaddr = DATA_START;
|
||||
rdata_section->s_paddr = DATA_START;
|
||||
rdata_section->s_scnptr = text_section->s_scnptr + hdr.aout.tsize;
|
||||
|
||||
data_section->s_vaddr = data_start;
|
||||
data_section->s_paddr = data_start;
|
||||
data_section->s_size = brk - data_start;
|
||||
data_section->s_scnptr = rdata_section->s_scnptr + rdata_section->s_size;
|
||||
vaddr = data_section->s_vaddr + data_section->s_size;
|
||||
scnptr = data_section->s_scnptr + data_section->s_size;
|
||||
if (lit8_section != NULL)
|
||||
{
|
||||
lit8_section->s_vaddr = vaddr;
|
||||
lit8_section->s_paddr = vaddr;
|
||||
lit8_section->s_size = 0;
|
||||
lit8_section->s_scnptr = scnptr;
|
||||
}
|
||||
if (lit4_section != NULL)
|
||||
{
|
||||
lit4_section->s_vaddr = vaddr;
|
||||
lit4_section->s_paddr = vaddr;
|
||||
lit4_section->s_size = 0;
|
||||
lit4_section->s_scnptr = scnptr;
|
||||
}
|
||||
if (sdata_section != NULL)
|
||||
{
|
||||
sdata_section->s_vaddr = vaddr;
|
||||
sdata_section->s_paddr = vaddr;
|
||||
sdata_section->s_size = 0;
|
||||
sdata_section->s_scnptr = scnptr;
|
||||
}
|
||||
if (sbss_section != NULL)
|
||||
{
|
||||
sbss_section->s_vaddr = vaddr;
|
||||
sbss_section->s_paddr = vaddr;
|
||||
sbss_section->s_size = 0;
|
||||
sbss_section->s_scnptr = scnptr;
|
||||
}
|
||||
if (bss_section != NULL)
|
||||
{
|
||||
bss_section->s_vaddr = vaddr;
|
||||
bss_section->s_paddr = vaddr;
|
||||
bss_section->s_size = 0;
|
||||
bss_section->s_scnptr = scnptr;
|
||||
}
|
||||
|
||||
WRITE (new, TEXT_START, hdr.aout.tsize,
|
||||
"writing text section to %s", new_name);
|
||||
WRITE (new, DATA_START, hdr.aout.dsize,
|
||||
"writing data section to %s", new_name);
|
||||
|
||||
SEEK (old, hdr.fhdr.f_symptr, "seeking to start of symbols in %s", a_name);
|
||||
errno = EEOF;
|
||||
nread = read (old, buffer, BUFSIZE);
|
||||
if (nread < sizeof (HDRR)) fatal_unexec ("reading symbols from %s", a_name);
|
||||
#define symhdr ((pHDRR)buffer)
|
||||
newsyms = hdr.aout.tsize + hdr.aout.dsize;
|
||||
symrel = newsyms - hdr.fhdr.f_symptr;
|
||||
hdr.fhdr.f_symptr = newsyms;
|
||||
symhdr->cbLineOffset += symrel;
|
||||
symhdr->cbDnOffset += symrel;
|
||||
symhdr->cbPdOffset += symrel;
|
||||
symhdr->cbSymOffset += symrel;
|
||||
symhdr->cbOptOffset += symrel;
|
||||
symhdr->cbAuxOffset += symrel;
|
||||
symhdr->cbSsOffset += symrel;
|
||||
symhdr->cbSsExtOffset += symrel;
|
||||
symhdr->cbFdOffset += symrel;
|
||||
symhdr->cbRfdOffset += symrel;
|
||||
symhdr->cbExtOffset += symrel;
|
||||
#undef symhdr
|
||||
do
|
||||
{
|
||||
if (write (new, buffer, nread) != nread)
|
||||
fatal_unexec ("writing symbols to %s", new_name);
|
||||
nread = read (old, buffer, BUFSIZE);
|
||||
if (nread < 0) fatal_unexec ("reading symbols from %s", a_name);
|
||||
#undef BUFSIZE
|
||||
} while (nread != 0);
|
||||
|
||||
SEEK (new, 0, "seeking to start of header in %s", new_name);
|
||||
WRITE (new, &hdr, sizeof (hdr),
|
||||
"writing header of %s", new_name);
|
||||
|
||||
close (old);
|
||||
close (new);
|
||||
mark_x (new_name);
|
||||
}
|
||||
|
||||
/*
|
||||
* mark_x
|
||||
*
|
||||
* After successfully building the new a.out, mark it executable
|
||||
*/
|
||||
|
||||
static void
|
||||
mark_x (name)
|
||||
char *name;
|
||||
{
|
||||
struct stat sbuf;
|
||||
int um = umask (777);
|
||||
umask (um);
|
||||
if (stat (name, &sbuf) < 0)
|
||||
fatal_unexec ("getting protection on %s", name);
|
||||
sbuf.st_mode |= 0111 & ~um;
|
||||
if (chmod (name, sbuf.st_mode) < 0)
|
||||
fatal_unexec ("setting protection on %s", name);
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_unexec (char *s, ...)
|
||||
{
|
||||
va_list ap;
|
||||
if (errno == EEOF)
|
||||
fputs ("unexec: unexpected end of file, ", stderr);
|
||||
else if (errno < sys_nerr)
|
||||
fprintf (stderr, "unexec: %s, ", sys_errlist[errno]);
|
||||
else
|
||||
fprintf (stderr, "unexec: error code %d, ", errno);
|
||||
va_start (ap, s);
|
||||
_doprnt (s, ap, stderr);
|
||||
fputs (".\n", stderr);
|
||||
exit (1);
|
||||
}
|
||||
|
|
@ -1,468 +0,0 @@
|
|||
/*
|
||||
* unexec for the NeXT Mach environment.
|
||||
*
|
||||
* Bradley Taylor (btaylor@NeXT.COM)
|
||||
* February 28, 1990
|
||||
*
|
||||
* Modified by Noritake Yonezawa (yonezawa@cs.uiuc.edu)
|
||||
* July 28, 1991
|
||||
*
|
||||
* Modified by Noritake Yonezawa (yone@vcdew25.lsi.tmg.nec.CO.JP)
|
||||
* February 16, 1992
|
||||
*/
|
||||
#undef __STRICT_BSD__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <mach.h>
|
||||
#include <sys/loader.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libc.h>
|
||||
|
||||
#define CEIL(x,quantum) ((((int)(x))+(quantum)-1)&~((quantum)-1))
|
||||
|
||||
int malloc_cookie;
|
||||
|
||||
#ifndef BIG_HEAP_SIZE
|
||||
#define BIG_HEAP_SIZE 0x1000000
|
||||
#endif
|
||||
|
||||
int big_heap = BIG_HEAP_SIZE;
|
||||
|
||||
char *mach_maplimit = 0;
|
||||
char *mach_brkpt = 0;
|
||||
|
||||
typedef struct region_t {
|
||||
vm_address_t address;
|
||||
vm_size_t size;
|
||||
vm_prot_t protection;
|
||||
vm_prot_t max_protection;
|
||||
vm_inherit_t inheritance;
|
||||
boolean_t shared;
|
||||
port_t object_name;
|
||||
vm_offset_t offset;
|
||||
} region_t;
|
||||
|
||||
char *
|
||||
my_sbrk(int incr)
|
||||
{
|
||||
char *temp, *ptr;
|
||||
kern_return_t rtn;
|
||||
|
||||
if (mach_brkpt == 0) {
|
||||
if ((rtn = vm_allocate(task_self(), (vm_address_t *) & mach_brkpt,
|
||||
big_heap, 1)) != KERN_SUCCESS) {
|
||||
mach_error("my_sbrk(): vm_allocate() failed", rtn);
|
||||
return ((char *)-1);
|
||||
}
|
||||
mach_maplimit = mach_brkpt + big_heap;
|
||||
}
|
||||
if (incr == 0) {
|
||||
return (mach_brkpt);
|
||||
} else {
|
||||
ptr = mach_brkpt + incr;
|
||||
if (ptr <= mach_maplimit) {
|
||||
temp = mach_brkpt;
|
||||
mach_brkpt = ptr;
|
||||
return (temp);
|
||||
} else {
|
||||
fprintf(stderr, "my_sbrk(): no more memory\n");
|
||||
fflush(stderr);
|
||||
return ((char *)-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
grow(
|
||||
struct load_command ***the_commands,
|
||||
unsigned *the_commands_len
|
||||
)
|
||||
{
|
||||
if (*the_commands == NULL) {
|
||||
*the_commands_len = 1;
|
||||
*the_commands = malloc(sizeof(*the_commands));
|
||||
} else {
|
||||
(*the_commands_len)++;
|
||||
*the_commands = realloc(*the_commands,
|
||||
(*the_commands_len *
|
||||
sizeof(**the_commands)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
save_command(
|
||||
struct load_command *command,
|
||||
struct load_command ***the_commands,
|
||||
unsigned *the_commands_len
|
||||
)
|
||||
{
|
||||
struct load_command **tmp;
|
||||
|
||||
grow(the_commands, the_commands_len);
|
||||
tmp = &(*the_commands)[*the_commands_len - 1];
|
||||
*tmp = malloc(command->cmdsize);
|
||||
bcopy(command, *tmp, command->cmdsize);
|
||||
}
|
||||
|
||||
static void
|
||||
fatal_unexec(char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
fprintf(stderr, "unexec: ");
|
||||
vfprintf(stderr, format, ap);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static int
|
||||
read_macho(
|
||||
int fd,
|
||||
struct mach_header *the_header,
|
||||
struct load_command ***the_commands,
|
||||
unsigned *the_commands_len
|
||||
)
|
||||
{
|
||||
struct load_command command;
|
||||
struct load_command *buf;
|
||||
int i;
|
||||
int size;
|
||||
|
||||
if (read(fd, the_header, sizeof(*the_header)) != sizeof(*the_header)) {
|
||||
fatal_unexec("cannot read macho header");
|
||||
return (0);
|
||||
}
|
||||
for (i = 0; i < the_header->ncmds; i++) {
|
||||
if (read(fd, &command, sizeof(struct load_command)) !=
|
||||
sizeof(struct load_command)) {
|
||||
fatal_unexec("cannot read macho load command header");
|
||||
return (0);
|
||||
}
|
||||
size = command.cmdsize - sizeof(struct load_command);
|
||||
if (size < 0) {
|
||||
fatal_unexec("bogus load command size");
|
||||
return (0);
|
||||
}
|
||||
buf = malloc(command.cmdsize);
|
||||
buf->cmd = command.cmd;
|
||||
buf->cmdsize = command.cmdsize;
|
||||
if (read(fd, ((char *)buf +
|
||||
sizeof(struct load_command)),
|
||||
size) != size) {
|
||||
fatal_unexec("cannot read load command data");
|
||||
return (0);
|
||||
}
|
||||
save_command(buf, the_commands, the_commands_len);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
filldatagap(
|
||||
vm_address_t start_address,
|
||||
vm_size_t *size,
|
||||
vm_address_t end_address
|
||||
)
|
||||
{
|
||||
vm_address_t address;
|
||||
vm_size_t gapsize;
|
||||
|
||||
address = (start_address + *size);
|
||||
gapsize = end_address - address;
|
||||
*size += gapsize;
|
||||
if (vm_allocate(task_self(), &address, gapsize,
|
||||
FALSE) != KERN_SUCCESS) {
|
||||
fatal_unexec("cannot vm_allocate");
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int
|
||||
get_data_region(
|
||||
vm_address_t *address,
|
||||
vm_size_t *size
|
||||
)
|
||||
{
|
||||
region_t region;
|
||||
kern_return_t ret;
|
||||
struct section *sect;
|
||||
|
||||
sect = (struct section *) getsectbyname(SEG_DATA, SECT_DATA);
|
||||
region.address = 0;
|
||||
*address = 0;
|
||||
for (;;) {
|
||||
ret = vm_region(task_self(),
|
||||
®ion.address,
|
||||
®ion.size,
|
||||
®ion.protection,
|
||||
®ion.max_protection,
|
||||
®ion.inheritance,
|
||||
®ion.shared,
|
||||
®ion.object_name,
|
||||
®ion.offset);
|
||||
if (ret != KERN_SUCCESS || region.address >= mach_maplimit) {
|
||||
break;
|
||||
}
|
||||
if (*address != 0) {
|
||||
if (region.address > *address + *size) {
|
||||
if (!filldatagap(*address, size,
|
||||
region.address)) {
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
*size += region.size;
|
||||
} else {
|
||||
if (region.address == sect->addr) {
|
||||
*address = region.address;
|
||||
*size = region.size;
|
||||
}
|
||||
}
|
||||
region.address += region.size;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
static char *
|
||||
my_malloc(
|
||||
vm_size_t size
|
||||
)
|
||||
{
|
||||
vm_address_t address;
|
||||
|
||||
if (vm_allocate(task_self(), &address, size, TRUE) != KERN_SUCCESS) {
|
||||
return (NULL);
|
||||
}
|
||||
return ((char *)address);
|
||||
}
|
||||
|
||||
static void
|
||||
my_free(
|
||||
char *buf,
|
||||
vm_size_t size
|
||||
)
|
||||
{
|
||||
vm_deallocate(task_self(), (vm_address_t)buf, size);
|
||||
}
|
||||
|
||||
static int
|
||||
unexec_doit(
|
||||
int infd,
|
||||
int outfd
|
||||
)
|
||||
{
|
||||
int i;
|
||||
struct load_command **the_commands = NULL;
|
||||
unsigned the_commands_len;
|
||||
struct mach_header the_header;
|
||||
int fgrowth;
|
||||
int fdatastart;
|
||||
int fdatasize;
|
||||
int size;
|
||||
int seg;
|
||||
struct stat st;
|
||||
char *buf;
|
||||
vm_address_t data_address;
|
||||
vm_size_t data_size, bss_size;
|
||||
|
||||
struct segment_command *segment;
|
||||
struct section *section;
|
||||
|
||||
if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (!get_data_region(&data_address, &data_size)) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* DO NOT USE MALLOC IN THIS SECTION
|
||||
*/
|
||||
{
|
||||
/*
|
||||
* Fix offsets
|
||||
*/
|
||||
for (i = 0; i < the_commands_len; i++) {
|
||||
switch (the_commands[i]->cmd) {
|
||||
case LC_SEGMENT:
|
||||
segment = ((struct segment_command *)
|
||||
the_commands[i]);
|
||||
if (strcmp(segment->segname, SEG_DATA) == 0) {
|
||||
data_size = CEIL(mach_brkpt - data_address, getpagesize());
|
||||
bss_size = mach_maplimit - mach_brkpt;
|
||||
fdatastart = segment->fileoff;
|
||||
fdatasize = segment->filesize;
|
||||
fgrowth = (data_size -
|
||||
segment->filesize);
|
||||
segment->vmsize = data_size + bss_size;
|
||||
segment->filesize = data_size;
|
||||
section = (struct section *) ((char *) (segment + 1));
|
||||
for (seg = 0; seg < segment->nsects; ++seg, ++section) {
|
||||
if (strcmp(section->sectname, SECT_DATA) == 0) {
|
||||
section->size = data_size;
|
||||
}
|
||||
else if (strcmp(section->sectname, SECT_BSS) == 0) {
|
||||
section->addr = data_address + data_size;
|
||||
section->size = bss_size;
|
||||
section->flags = S_ZEROFILL;
|
||||
}
|
||||
else if (strcmp(section->sectname, SECT_COMMON) == 0) {
|
||||
section->addr = data_address + data_size + bss_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (strcmp(segment->segname, SEG_LINKEDIT) == 0) {
|
||||
segment->vmaddr += CEIL(fgrowth + bss_size, getpagesize());
|
||||
segment->fileoff += fgrowth;
|
||||
}
|
||||
break;
|
||||
case LC_SYMTAB:
|
||||
((struct symtab_command *)
|
||||
the_commands[i])->symoff += fgrowth;
|
||||
((struct symtab_command *)
|
||||
the_commands[i])->stroff += fgrowth;
|
||||
break;
|
||||
case LC_SYMSEG:
|
||||
((struct symseg_command *)
|
||||
the_commands[i])->offset += fgrowth;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write header
|
||||
*/
|
||||
if (write(outfd, &the_header,
|
||||
sizeof(the_header)) != sizeof(the_header)) {
|
||||
fatal_unexec("cannot write header");
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write commands
|
||||
*/
|
||||
for (i = 0; i < the_commands_len; i++) {
|
||||
if (write(outfd, the_commands[i],
|
||||
the_commands[i]->cmdsize) !=
|
||||
the_commands[i]->cmdsize) {
|
||||
fatal_unexec("cannot write commands");
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Write original text
|
||||
*/
|
||||
if (lseek(infd, the_header.sizeofcmds + sizeof(the_header),
|
||||
L_SET) < 0) {
|
||||
fatal_unexec("cannot seek input file");
|
||||
return (0);
|
||||
}
|
||||
size = fdatastart - (sizeof(the_header) +
|
||||
the_header.sizeofcmds);
|
||||
buf = my_malloc(size);
|
||||
if (read(infd, buf, size) != size) {
|
||||
my_free(buf, size);
|
||||
fatal_unexec("cannot read input file");
|
||||
}
|
||||
if (write(outfd, buf, size) != size) {
|
||||
my_free(buf, size);
|
||||
fatal_unexec("cannot write original text");
|
||||
return (0);
|
||||
}
|
||||
my_free(buf, size);
|
||||
|
||||
|
||||
/*
|
||||
* Write new data
|
||||
*/
|
||||
if (write(outfd, (char *)data_address,
|
||||
data_size) != data_size) {
|
||||
fatal_unexec("cannot write new data");
|
||||
return (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* OKAY TO USE MALLOC NOW
|
||||
*/
|
||||
|
||||
/*
|
||||
* Write rest of file
|
||||
*/
|
||||
fstat(infd, &st);
|
||||
if (lseek(infd, fdatasize, L_INCR) < 0) {
|
||||
fatal_unexec("cannot seek input file");
|
||||
return (0);
|
||||
}
|
||||
size = st.st_size - lseek(infd, 0, L_INCR);
|
||||
|
||||
buf = malloc(size);
|
||||
if (read(infd, buf, size) != size) {
|
||||
free(buf);
|
||||
fatal_unexec("cannot read input file");
|
||||
return (0);
|
||||
}
|
||||
if (write(outfd, buf, size) != size) {
|
||||
free(buf);
|
||||
fatal_unexec("cannot write reset of file");
|
||||
return (0);
|
||||
}
|
||||
free(buf);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void
|
||||
unexec(
|
||||
char *outfile,
|
||||
char *infile
|
||||
)
|
||||
{
|
||||
int infd;
|
||||
int outfd;
|
||||
char tmpbuf[L_tmpnam];
|
||||
char *tmpfile;
|
||||
|
||||
infd = open(infile, O_RDONLY, 0);
|
||||
if (infd < 0) {
|
||||
fatal_unexec("cannot open input file `%s'", infile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tmpnam(tmpbuf);
|
||||
tmpfile = rindex(tmpbuf, '/');
|
||||
if (tmpfile == NULL) {
|
||||
tmpfile = tmpbuf;
|
||||
} else {
|
||||
tmpfile++;
|
||||
}
|
||||
outfd = open(tmpfile, O_WRONLY|O_TRUNC|O_CREAT, 0755);
|
||||
if (outfd < 0) {
|
||||
close(infd);
|
||||
fatal_unexec("cannot open tmp file `%s'", tmpfile);
|
||||
exit(1);
|
||||
}
|
||||
if (!unexec_doit(infd, outfd)) {
|
||||
close(infd);
|
||||
close(outfd);
|
||||
unlink(tmpfile);
|
||||
exit(1);
|
||||
}
|
||||
close(infd);
|
||||
close(outfd);
|
||||
if (rename(tmpfile, outfile) < 0) {
|
||||
unlink(tmpfile);
|
||||
fatal_unexec("cannot rename `%s' to `%s'", tmpfile, outfile);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
/* Contributed by Viktor Dukhovni. */
|
||||
/*
|
||||
* Unexec for Berkeley a.out format + SUNOS shared libraries
|
||||
* The unexeced executable contains the __DYNAMIC area from the
|
||||
* original text file, and then the rest of data + bss + malloced area of
|
||||
* the current process. (The __DYNAMIC area is at the top of the process
|
||||
* data segment, we use "data_start" defined externally to mark the start
|
||||
* of the "real" data segment.)
|
||||
*
|
||||
* For programs that want to remap some of the data segment read only
|
||||
* a run_time_remap is provided. This attempts to remap largest area starting
|
||||
* and ending on page boundaries between "data_start" and "bndry"
|
||||
* For this it to figure out where the text file is located. A path search
|
||||
* is attempted after trying argv[0] and if all fails we simply do not remap
|
||||
*
|
||||
* One feature of run_time_remap () is mandatory: reseting the break.
|
||||
*
|
||||
* Note that we can no longer map data into the text segment, as this causes
|
||||
* the __DYNAMIC struct to become read only, breaking the runtime loader.
|
||||
* Thus we no longer need to mess with a private crt0.c, the standard one
|
||||
* will do just fine, since environ can live in the writable area between
|
||||
* __DYNAMIC and data_start, just make sure that pre-crt0.o (the name
|
||||
* is somewhat abused here) is loaded first!
|
||||
*
|
||||
*/
|
||||
#ifdef emacs
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <a.out.h>
|
||||
|
||||
/*
|
||||
* for programs other than emacs
|
||||
* define data_start + initialized here, and make sure
|
||||
* this object is loaded first!
|
||||
* emacs will define these elsewhere, and load the object containing
|
||||
* data_start (pre-crt0.o or firstfile.o?) first!
|
||||
* The custom crt0.o *must not* be loaded!
|
||||
*/
|
||||
#ifndef emacs
|
||||
static int data_start = 0;
|
||||
static int initialized = 0;
|
||||
#else
|
||||
extern int initialized;
|
||||
extern unsigned data_start;
|
||||
extern int pureptr;
|
||||
#endif
|
||||
|
||||
extern char *getenv ();
|
||||
static unsigned Brk;
|
||||
static struct exec nhdr;
|
||||
static int rd_only_len;
|
||||
static long cookie;
|
||||
|
||||
|
||||
unexec (new_name, a_name, bndry, bss_start, entry)
|
||||
char *new_name, *a_name;
|
||||
unsigned bndry, bss_start, entry;
|
||||
{
|
||||
char buf[PAGSIZ];
|
||||
int fd, new;
|
||||
char *old;
|
||||
struct exec ohdr; /* Allocate on the stack, not needed in the next life */
|
||||
struct stat stat;
|
||||
|
||||
#ifdef emacs
|
||||
fprintf (stderr, "Used %d bytes of Pure Storage\n", pureptr);
|
||||
#endif
|
||||
|
||||
if ((fd = open (a_name, O_RDONLY)) < 0)
|
||||
{
|
||||
fprintf (stderr, "%s: open: ", a_name);
|
||||
perror (a_name);
|
||||
exit (1);
|
||||
}
|
||||
if ((new = open (new_name, O_WRONLY | O_CREAT, 0666)) == -1)
|
||||
{
|
||||
fprintf (stderr, "%s: open: ", a_name);
|
||||
perror (new_name);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if ((fstat (fd, &stat) == -1))
|
||||
{
|
||||
fprintf (stderr, "%s: ", a_name);
|
||||
perror ("fstat");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
old = (char *)mmap (0, stat.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (old == (char *)-1)
|
||||
{
|
||||
fprintf (stderr, "%s: ", a_name);
|
||||
perror ("mmap");
|
||||
exit (1);
|
||||
}
|
||||
close (fd);
|
||||
|
||||
nhdr = ohdr = (*(struct exec *)old);
|
||||
|
||||
|
||||
/*
|
||||
* Remember a magic cookie so we know we've got the right binary
|
||||
* when remapping.
|
||||
*/
|
||||
cookie = time (0);
|
||||
|
||||
Brk = sbrk (0); /* Save the break, it is reset to &_end (by ld.so?) */
|
||||
|
||||
/*
|
||||
* Round up data start to a page boundary (Lose if not a 2 power!)
|
||||
*/
|
||||
data_start = ((((int)&data_start) - 1) & ~(N_PAGSIZ (nhdr) - 1)) + N_PAGSIZ (nhdr);
|
||||
|
||||
/*
|
||||
* Round down read only pages to a multiple of the page size
|
||||
*/
|
||||
if (bndry)
|
||||
rd_only_len = ((int)bndry & ~(N_PAGSIZ (nhdr) - 1)) - data_start;
|
||||
|
||||
#ifndef emacs
|
||||
/* Have to do this some time before dumping the data */
|
||||
initialized = 1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Handle new data and bss sizes and optional new entry point.
|
||||
* No one actually uses bss_start and entry, but tradition compels
|
||||
* one to support them.
|
||||
* Could complain if bss_start > Brk, but the caller is *supposed* to know
|
||||
* what she is doing.
|
||||
*/
|
||||
nhdr.a_data = (bss_start ? bss_start : Brk) - N_DATADDR (nhdr);
|
||||
nhdr.a_bss = bss_start ? Brk - bss_start : 0;
|
||||
if (entry)
|
||||
nhdr.a_entry = entry;
|
||||
|
||||
/*
|
||||
* Write out the text segment with new header
|
||||
* Dynamic executables are ZMAGIC with N_TXTOFF==0 and the header
|
||||
* part of the text segment, but no need to rely on this.
|
||||
* So write the TEXT first, then go back replace the header.
|
||||
* Doing it in the other order is less general!
|
||||
*/
|
||||
lseek (new, N_TXTOFF (nhdr), L_SET);
|
||||
write (new, old + N_TXTOFF (ohdr), N_TXTOFF (ohdr) + ohdr.a_text);
|
||||
lseek (new, 0L, L_SET);
|
||||
write (new, &nhdr, sizeof (nhdr));
|
||||
|
||||
/*
|
||||
* Write out the head of the old data segment from the file not
|
||||
* from core, this has the unresolved __DYNAMIC relocation data
|
||||
* we need to reload
|
||||
*/
|
||||
lseek (new, N_DATOFF (nhdr), L_SET);
|
||||
write (new, old + N_DATOFF (ohdr), (int)&data_start - N_DATADDR (ohdr));
|
||||
|
||||
/*
|
||||
* Copy the rest of the data from core
|
||||
*/
|
||||
write (new, &data_start, N_BSSADDR (nhdr) - (int)&data_start);
|
||||
|
||||
/*
|
||||
* Copy the symbol table and line numbers
|
||||
*/
|
||||
lseek (new, N_TRELOFF (nhdr), L_SET);
|
||||
write (new, old + N_TRELOFF (ohdr), stat.st_size - N_TRELOFF (ohdr));
|
||||
|
||||
fchmod (new, 0755);
|
||||
}
|
||||
|
||||
void
|
||||
run_time_remap (progname)
|
||||
char *progname;
|
||||
{
|
||||
char aout[MAXPATHLEN];
|
||||
register char *path, *p;
|
||||
|
||||
/* Just in case */
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
/* Restore the break */
|
||||
brk (Brk);
|
||||
|
||||
/* If nothing to remap: we are done! */
|
||||
if (rd_only_len == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Attempt to find the executable
|
||||
* First try argv[0], will almost always succeed as shells tend to give
|
||||
* the full path from the hash list rather than using execvp ()
|
||||
*/
|
||||
if (is_it (progname))
|
||||
return;
|
||||
|
||||
/*
|
||||
* If argv[0] is a full path and does not exist, not much sense in
|
||||
* searching further
|
||||
*/
|
||||
if (strchr (progname, '/'))
|
||||
return;
|
||||
|
||||
/*
|
||||
* Try to search for argv[0] on the PATH
|
||||
*/
|
||||
path = getenv ("PATH");
|
||||
if (path == NULL)
|
||||
return;
|
||||
|
||||
while (*path)
|
||||
{
|
||||
/* copy through ':' or end */
|
||||
for (p = aout; *p = *path; ++p, ++path)
|
||||
if (*p == ':')
|
||||
{
|
||||
++path; /* move past ':' */
|
||||
break;
|
||||
}
|
||||
*p++ = '/';
|
||||
strcpy (p, progname);
|
||||
/*
|
||||
* aout is a candidate full path name
|
||||
*/
|
||||
if (is_it (aout))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
is_it (path)
|
||||
char *path;
|
||||
{
|
||||
int fd;
|
||||
long paths_cookie;
|
||||
struct exec hdr;
|
||||
|
||||
/*
|
||||
* Open an executable and check for a valid header!
|
||||
* Can't bcmp() the header with what we had, it may have been stripped!
|
||||
* so we may save looking at non executables with the same name, mostly
|
||||
* directories.
|
||||
*/
|
||||
fd = open (path, O_RDONLY);
|
||||
if (fd != -1)
|
||||
{
|
||||
if (read (fd, &hdr, sizeof (hdr)) == sizeof (hdr)
|
||||
&& !N_BADMAG (hdr) && N_DATOFF (hdr) == N_DATOFF (nhdr)
|
||||
&& N_TRELOFF (hdr) == N_TRELOFF (nhdr))
|
||||
{
|
||||
/* compare cookies */
|
||||
lseek (fd, N_DATOFF (hdr) + (int)&cookie - N_DATADDR (hdr), L_SET);
|
||||
read (fd, &paths_cookie, sizeof (paths_cookie));
|
||||
if (paths_cookie == cookie)
|
||||
{ /* Eureka */
|
||||
|
||||
/*
|
||||
* Do the mapping
|
||||
* The PROT_EXEC may not be needed, but it is safer this way.
|
||||
* should the shared library decide to indirect through
|
||||
* addresses in the data segment not part of __DYNAMIC
|
||||
*/
|
||||
mmap (data_start, rd_only_len, PROT_READ | PROT_EXEC,
|
||||
MAP_SHARED | MAP_FIXED, fd,
|
||||
N_DATOFF (hdr) + data_start - N_DATADDR (hdr));
|
||||
close (fd);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
close (fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 1984, Taiichi Yuasa and Masami Hagiya.
|
||||
Copyright (c) 1990, Giuseppe Attardi.
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
See file '../Copyright' for full details.
|
||||
*/
|
||||
|
||||
/*
|
||||
unixsave.c
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "page.h"
|
||||
#include "objff.h"
|
||||
#include <sys/file.h>
|
||||
|
||||
#ifdef COFF
|
||||
# define a_text tsize
|
||||
# define a_data dsize
|
||||
# define a_bss bsize
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef apollo
|
||||
# define SEGSIZ 65536
|
||||
#endif
|
||||
|
||||
#ifdef IBMRT
|
||||
# define PAGE_SIZE 2048
|
||||
#endif
|
||||
|
||||
#ifdef SEQ
|
||||
# define SEGSIZ 2048
|
||||
#endif
|
||||
|
||||
#ifdef TAHOE
|
||||
# define SEGSIZ 1024
|
||||
#endif
|
||||
|
||||
#ifdef VAX
|
||||
# define PAGE_SIZE 1024
|
||||
# define SEGSIZ 1024
|
||||
#endif
|
||||
|
||||
#ifndef TXTRELOC
|
||||
# define TXTRELOC 0
|
||||
#endif
|
||||
|
||||
filecpy(FILE *to, FILE *from, register int n)
|
||||
{
|
||||
char buffer[BUFSIZ];
|
||||
|
||||
while (n > BUFSIZ) {
|
||||
fread(buffer, BUFSIZ, 1, from);
|
||||
fwrite(buffer, BUFSIZ, 1, to);
|
||||
n -= BUFSIZ;
|
||||
}
|
||||
if (n > 0) {
|
||||
fread(buffer, 1, n, from);
|
||||
fwrite(buffer, 1, n, to);
|
||||
}
|
||||
}
|
||||
|
||||
#define ADJUST(field) if (field) field += diff
|
||||
|
||||
unexec(char *save_file, char *original_file,
|
||||
unsigned data_start, unsigned bss_start, unsigned entry_address)
|
||||
{
|
||||
#ifdef AOUT
|
||||
struct exec header;
|
||||
#endif AOUT
|
||||
#ifdef COFF
|
||||
FILHDR fileheader;
|
||||
AOUTHDR header;
|
||||
SCNHDR sectionheader;
|
||||
long diff, text_scnptr;
|
||||
#endif COFF
|
||||
|
||||
char *data_begin;
|
||||
int text_size, data_size, bss_size, str_size, data_padding;
|
||||
FILE *original, *save, *standard_error;
|
||||
register int n;
|
||||
register char *p;
|
||||
|
||||
extern char stdin_buf[BUFSIZ], stdout_buf[BUFSIZ];
|
||||
|
||||
_cleanup();
|
||||
|
||||
original = freopen(original_file, OPEN_R, stdin);
|
||||
if (stdin != original || fileno(original) != 0) {
|
||||
fprintf(stderr, "Can't open the original file.\n");
|
||||
exit(1);
|
||||
}
|
||||
setbuf(original, stdin_buf);
|
||||
|
||||
#ifndef apollo
|
||||
/* not unlinking the previous executable is a trick since I dont know
|
||||
how to create a file whose type is COFF (rather then unstruct) */
|
||||
unlink(save_file);
|
||||
#endif apollo
|
||||
|
||||
#ifdef MSDOS
|
||||
save = fopen(save_file, OPEN_W);
|
||||
#else
|
||||
save = freopen(save_file, OPEN_W, stdout);
|
||||
#endif
|
||||
chmod(save_file, 0775);
|
||||
setbuf(save, stdout_buf); /* avoid malloc call by fwrite */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
#ifdef AOUT
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
# if defined(VAX) || defined(NEWS) || defined(SEQ) || defined(TAHOE)
|
||||
# define N_DATADDR(hdr) ((TXTRELOC + hdr.a_text+(SEGSIZ-1)) & ~(SEGSIZ-1))
|
||||
# elif defined(IBMRT)
|
||||
# define N_DATADDR(hdr) (TXTRELOC + hdr.a_text);
|
||||
# elif defined(hp9000s300)
|
||||
# define N_DATADDR(hdr) ((hdr.a_magic.file_type == SHARE_MAGIC || \
|
||||
hdr.a_magic.file_type == DEMAND_MAGIC) ? \
|
||||
EXEC_ALIGN(hdr.a_text) : hdr.a_text);
|
||||
# endif
|
||||
|
||||
n = 3; /* section count */
|
||||
fread(&header, sizeof(header), 1, original);
|
||||
|
||||
data_begin = (char *)N_DATADDR(header);
|
||||
text_size = N_DATOFF(header) - N_TXTOFF(header);
|
||||
data_size = header.a_data;
|
||||
bss_size = header.a_bss;
|
||||
|
||||
/* The file generated will have:
|
||||
1. updated header;
|
||||
2. same text section as original;
|
||||
3. data section dumped from memory;
|
||||
4. bss section empty;
|
||||
5. syms, trel and drel sections as original;
|
||||
6. strings as original.
|
||||
*/
|
||||
/* Update header before writing */
|
||||
header.a_data = data_end - data_begin;
|
||||
# if defined(__linux__) || defined(__EMX__)
|
||||
data_padding = SEGMENT_SIZE - header.a_data % SEGMENT_SIZE;
|
||||
header.a_data += data_padding;
|
||||
# endif
|
||||
header.a_bss = 0;
|
||||
fwrite(&header, sizeof(header), 1, save);
|
||||
|
||||
# if defined(__linux__) || defined(__EMX__)
|
||||
if (N_MAGIC(header) == QMAGIC)
|
||||
filecpy(save, original, text_size - sizeof(header));
|
||||
else
|
||||
filecpy(save, original, text_size + _N_HDROFF(header));
|
||||
# elif defined(MSDOS)
|
||||
filecpy(save, original, text_size);
|
||||
# elif defined(SEQ)
|
||||
filecpy(save, original, header.a_text -
|
||||
N_ADDRADJ(header) - sizeof(header));
|
||||
# elif defined(hp9000s300)
|
||||
if (header.a_magic.file_type == DEMAND_MAGIC) {
|
||||
filecpy(save, original, EXEC_PAGESIZE - sizeof(header));
|
||||
filecpy(save, original, EXEC_ALIGN(header.a_text));}
|
||||
else
|
||||
filecpy(save, original, header.a_text);
|
||||
# elif defined(vax) || defined(NEWS) || defined(IBMRT)
|
||||
if (N_MAGIC(header) == ZMAGIC)
|
||||
filecpy(save, original, PAGE_SIZE - sizeof(header));
|
||||
filecpy(save, original, header.a_text);
|
||||
# elif defined(BSD)
|
||||
filecpy(save, original, header.a_text - sizeof(header));
|
||||
# endif
|
||||
#endif AOUT
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
#ifdef COFF
|
||||
/* ---------------------------------------------------------------------- */
|
||||
n = 0; /* section count */
|
||||
fread(&fileheader, sizeof(fileheader), 1, original);
|
||||
fread(&header, sizeof(header), 1, original);
|
||||
|
||||
data_begin = (char *)header.data_start;
|
||||
# ifdef apollo
|
||||
data_begin += FILHSZ + sizeof(header)
|
||||
+ fileheader.f_nscns * sizeof(struct scnhdr);
|
||||
# endif apollo
|
||||
data_size = header.a_data;
|
||||
header.a_data = data_end - data_begin;
|
||||
diff = header.a_data - data_size;
|
||||
fileheader.f_symptr += diff;
|
||||
fwrite(&fileheader, sizeof(fileheader), 1, save);
|
||||
|
||||
header.a_bss = 0;
|
||||
# ifdef apollo
|
||||
header.o_sri += diff;
|
||||
header.o_inlib += diff;
|
||||
# endif apollo
|
||||
# ifdef __mips
|
||||
header.bss_start = header.data_start + header.a_data;
|
||||
/* tsize includes headers which are also loaded into memory */
|
||||
# endif __mips
|
||||
|
||||
fwrite(&header, sizeof(header), 1, save);
|
||||
|
||||
/* .text */
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
text_scnptr = sectionheader.s_scnptr;
|
||||
ADJUST(sectionheader.s_relptr);
|
||||
ADJUST(sectionheader.s_lnnoptr);
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
|
||||
# ifdef apollo
|
||||
|
||||
/* .unwind */
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
ADJUST(sectionheader.s_relptr);
|
||||
ADJUST(sectionheader.s_lnnoptr);
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
|
||||
/* .aptv */
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
ADJUST(sectionheader.s_relptr);
|
||||
ADJUST(sectionheader.s_lnnoptr);
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
# endif apollo
|
||||
|
||||
# ifdef ECOFF
|
||||
|
||||
/* .init */
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
|
||||
/* .data */
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
|
||||
/* .rdata */
|
||||
# else
|
||||
/* .data */
|
||||
# endif ECOFF
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
n++;
|
||||
sectionheader.s_size += diff;
|
||||
# ifdef apollo
|
||||
/* the APTV at the beginning of data section has already
|
||||
been relocated at first initialization.
|
||||
Avoid doing it again.
|
||||
*/
|
||||
sectionheader.s_nreloc = 0;
|
||||
# endif apollo
|
||||
ADJUST(sectionheader.s_relptr);
|
||||
ADJUST(sectionheader.s_lnnoptr);
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
|
||||
/* copy all remaining section headers */
|
||||
for (; n < fileheader.f_nscns; n++) {
|
||||
fread(§ionheader, sizeof(sectionheader), 1, original);
|
||||
if (strcmp(sectionheader.s_name, ".bss") == 0) {
|
||||
sectionheader.s_size = header.a_bss;
|
||||
ADJUST(sectionheader.s_paddr);
|
||||
ADJUST(sectionheader.s_vaddr);
|
||||
}
|
||||
ADJUST(sectionheader.s_scnptr);
|
||||
ADJUST(sectionheader.s_relptr);
|
||||
ADJUST(sectionheader.s_lnnoptr);
|
||||
fwrite(§ionheader, sizeof(sectionheader), 1, save);
|
||||
}
|
||||
|
||||
/* copy the text section */
|
||||
text_size = header.a_text;
|
||||
# ifdef MSDOS
|
||||
# define SECTION_ALIGNMENT 1023
|
||||
# define ADJUST_TEXT_SCNHDR_SIZE
|
||||
# endif
|
||||
# ifdef SECTION_ALIGNMENT
|
||||
/* Some systems require special alignment
|
||||
of the sections in the file itself. */
|
||||
text_size = (text_size + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
|
||||
# endif
|
||||
# ifdef ADJUST_TEXT_SCNHDR_SIZE
|
||||
/* On some machines, `text size' includes all headers. */
|
||||
text_size -= FILHSZ + AOUTSZ + SCNHSZ * fileheader.f_nscns;
|
||||
# endif
|
||||
filecpy(save, original, text_size);
|
||||
|
||||
#endif COFF
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/* write the new data section */
|
||||
#if defined(__linux__) || defined(__EMX__)
|
||||
/* The heap starts at a SEGMENT_SIZE boundary */
|
||||
for (n = data_size + bss_size, p = data_begin; n > BUFSIZ ;
|
||||
n -= BUFSIZ, p += BUFSIZ)
|
||||
fwrite(p, BUFSIZ, 1, save);
|
||||
if (n > 0)
|
||||
fwrite(p, 1, n, save);
|
||||
n = SEGMENT_SIZE - (data_size + bss_size) % SEGMENT_SIZE;
|
||||
/* write 0's to fill gap */
|
||||
{ int j; char pad[512];
|
||||
for (j = n; j > 512 ; j -= 512)
|
||||
fwrite(&pad, 512, 1, save);
|
||||
if (j > 0)
|
||||
fwrite(&pad, 1, j, save);
|
||||
}
|
||||
header.a_data -= data_size + bss_size + n + data_padding;
|
||||
data_begin += data_size + bss_size + n;
|
||||
#endif
|
||||
for (n = header.a_data, p = data_begin; n > BUFSIZ ;
|
||||
n -= BUFSIZ, p += BUFSIZ)
|
||||
fwrite(p, BUFSIZ, 1, save);
|
||||
if (n > 0)
|
||||
fwrite(p, 1, n, save);
|
||||
|
||||
#if defined(__linux__) || defined(__EMX__)
|
||||
/* pad data section up to SEGMENT_SIZE */
|
||||
{ int j; char pad[512];
|
||||
for (j = data_padding; j > 512 ; j -= 512)
|
||||
fwrite(&pad, 512, 1, save);
|
||||
if (j > 0)
|
||||
fwrite(&pad, 1, j, save);
|
||||
}
|
||||
#endif __EMX__
|
||||
|
||||
/* skip data section of original file */
|
||||
fseek(original, data_size, 1);
|
||||
|
||||
#ifdef hpux
|
||||
fseek(save, MODCAL_OFFSET(header), 0);
|
||||
header.a_data = data_size;
|
||||
fseek(original, MODCAL_OFFSET(header), 0);
|
||||
#endif hpux
|
||||
|
||||
#ifdef ECOFF
|
||||
{ HDRR symhdr;
|
||||
|
||||
/* copy up to Symbol Table */
|
||||
filecpy(save, original, N_SYMOFF(fileheader) - ftell(original));
|
||||
/* update Symbol Table Header */
|
||||
fread(&symhdr, cbHDRR, 1, original);
|
||||
ADJUST(symhdr.cbLineOffset);
|
||||
ADJUST(symhdr.cbDnOffset);
|
||||
ADJUST(symhdr.cbPdOffset);
|
||||
ADJUST(symhdr.cbSymOffset);
|
||||
ADJUST(symhdr.cbOptOffset);
|
||||
ADJUST(symhdr.cbAuxOffset);
|
||||
ADJUST(symhdr.cbSsOffset);
|
||||
ADJUST(symhdr.cbSsExtOffset);
|
||||
ADJUST(symhdr.cbFdOffset);
|
||||
ADJUST(symhdr.cbRfdOffset);
|
||||
ADJUST(symhdr.cbExtOffset);
|
||||
|
||||
fwrite(&symhdr, cbHDRR, 1, save);
|
||||
}
|
||||
#endif ECOFF
|
||||
|
||||
/* Copy the rest */
|
||||
filecpy(save, original, file_len(original) - ftell(original));
|
||||
fclose(original);
|
||||
fclose(save);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue