mirror of
https://github.com/autc04/Retro68.git
synced 2026-04-27 02:18:53 +00:00
Merge pull request #27 from autc04/segments
Segments: Multiple-segment Apps for 68K. UnloadSeg is still missing.
This commit is contained in:
@@ -1,6 +1,3 @@
|
||||
CIncludes*
|
||||
RIncludes*
|
||||
Universal Headers*
|
||||
*~
|
||||
.*.swp
|
||||
CMakeLists.txt.user
|
||||
|
||||
+4
-2
@@ -15,8 +15,9 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
project(Retro)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Retro.*)
|
||||
|
||||
@@ -54,10 +55,11 @@ configure_file(cmake/intree.toolchain.cmake.in cmake/intree.toolchain.cmake @ONL
|
||||
configure_file(cmake/intreeppc.toolchain.cmake.in cmake/intreeppc.toolchain.cmake @ONLY)
|
||||
configure_file(cmake/intreecarbon.toolchain.cmake.in cmake/intreecarbon.toolchain.cmake @ONLY)
|
||||
|
||||
add_subdirectory(libelf)
|
||||
add_subdirectory(ResourceFiles)
|
||||
add_subdirectory(MakeAPPL)
|
||||
add_subdirectory(Rez)
|
||||
add_subdirectory(ConvertObj)
|
||||
add_subdirectory(PEFTools)
|
||||
|
||||
add_subdirectory(Elf2Mac)
|
||||
endif()
|
||||
|
||||
@@ -26,6 +26,9 @@ add_library(RetroConsole
|
||||
MacUtils.h
|
||||
InitConsole.cc
|
||||
)
|
||||
set_target_properties(retrocrt
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS -ffunction-sections)
|
||||
|
||||
install(TARGETS RetroConsole DESTINATION lib)
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ using namespace Retro;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<WindowPtr, ConsoleWindow*> windows;
|
||||
std::unordered_map<WindowPtr, ConsoleWindow*> *windows = NULL;
|
||||
}
|
||||
|
||||
ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
|
||||
@@ -46,14 +46,16 @@ ConsoleWindow::ConsoleWindow(Rect r, ConstStr255Param title)
|
||||
SetPort(port);
|
||||
EraseRect(&portRect);
|
||||
|
||||
windows[win] = this;
|
||||
if(!windows)
|
||||
windows = new std::unordered_map<WindowPtr, ConsoleWindow*>();
|
||||
(*windows)[win] = this;
|
||||
|
||||
Init(port, portRect);
|
||||
}
|
||||
|
||||
ConsoleWindow::~ConsoleWindow()
|
||||
{
|
||||
windows.erase(win);
|
||||
windows->erase(win);
|
||||
DisposeWindow(win);
|
||||
}
|
||||
|
||||
@@ -85,7 +87,7 @@ char ConsoleWindow::WaitNextChar()
|
||||
{
|
||||
case updateEvt:
|
||||
eventWin = (WindowPtr)event.message;
|
||||
realConsole = windows[(WindowPtr)event.message];
|
||||
realConsole = (*windows)[(WindowPtr)event.message];
|
||||
if(realConsole)
|
||||
{
|
||||
Rect updateRect;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <string>
|
||||
#include "BinaryIO.h"
|
||||
#include <stdint.h>
|
||||
@@ -66,6 +67,8 @@ struct Module
|
||||
unordered_map<uint32_t, vector<string>> labels;
|
||||
unordered_map<uint32_t, Reloc> relocs;
|
||||
|
||||
std::vector<std::weak_ptr<Module>> nearrefs;
|
||||
|
||||
void write(std::ostream& out);
|
||||
};
|
||||
|
||||
@@ -107,8 +110,9 @@ string encodeIdentifier(const string& s)
|
||||
void Module::write(std::ostream& out)
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
string encodedName = encodeIdentifier(sectionMap[name]);
|
||||
|
||||
out << "\t.section .text." << encodeIdentifier(sectionMap[name]) << ",\"ax\",@progbits\n";
|
||||
out << "\t.section .text." << encodedName << ",\"ax\",@progbits\n";
|
||||
|
||||
while(offset < bytes.size())
|
||||
{
|
||||
@@ -134,15 +138,95 @@ void Module::write(std::ostream& out)
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
out << "\t.section .text." << encodedName << ".macsbug,\"ax\",@progbits\n";
|
||||
if(encodedName.size() < 32)
|
||||
out << "\t.byte " << (encodedName.size() | 0x80) << "\n";
|
||||
else
|
||||
out << "\t.byte 0x80\n"
|
||||
<< "\t.byte " << encodedName.size() << "\n";
|
||||
out << "\t.ascii \"" << encodedName << "\"\n";
|
||||
out << "\t.align 2,0\n\t.short 0\n";
|
||||
|
||||
out << "# ######\n\n";
|
||||
}
|
||||
|
||||
void sortModules(std::vector<std::shared_ptr<Module>>& modules)
|
||||
{
|
||||
std::unordered_set<std::shared_ptr<Module>> unemitted;
|
||||
for(auto& m : modules)
|
||||
unemitted.insert(m);
|
||||
|
||||
std::unordered_map<std::string, std::shared_ptr<Module>> nameMap;
|
||||
for(auto& m : modules)
|
||||
for(auto& l : m->labels)
|
||||
for(auto& str : l.second)
|
||||
nameMap[str] = m;
|
||||
|
||||
|
||||
for(auto& m : modules)
|
||||
for(auto& r : m->relocs)
|
||||
{
|
||||
if(r.second.size != 2)
|
||||
continue;
|
||||
if(r.second.name2.empty())
|
||||
{
|
||||
std::shared_ptr<Module> m1;
|
||||
m1 = nameMap.find(r.second.name1)->second;
|
||||
m1->nearrefs.push_back(m);
|
||||
m->nearrefs.push_back(m1);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::shared_ptr<Module> m1;
|
||||
m1 = nameMap.find(r.second.name1)->second;
|
||||
std::shared_ptr<Module> m2;
|
||||
m2 = nameMap.find(r.second.name2)->second;
|
||||
m1->nearrefs.push_back(m2);
|
||||
m2->nearrefs.push_back(m1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::shared_ptr<Module>> sorted;
|
||||
sorted.reserve(modules.size());
|
||||
|
||||
auto p = sorted.begin();
|
||||
|
||||
while(!unemitted.empty())
|
||||
{
|
||||
while(p != sorted.end())
|
||||
{
|
||||
for(auto& m2weak : (*p)->nearrefs)
|
||||
{
|
||||
if(std::shared_ptr<Module> m2 = m2weak.lock())
|
||||
{
|
||||
auto unemittedP = unemitted.find(m2);
|
||||
if(unemittedP != unemitted.end())
|
||||
{
|
||||
sorted.push_back(m2);
|
||||
unemitted.erase(unemittedP);
|
||||
}
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
sorted.push_back(*unemitted.begin());
|
||||
unemitted.erase(unemitted.begin());
|
||||
}
|
||||
|
||||
sorted.swap(modules);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
std::ifstream in(argv[1]);
|
||||
|
||||
unordered_map<int,string> stringDictionary;
|
||||
std::unique_ptr<Module> module;
|
||||
|
||||
bool shouldSortModules = true;
|
||||
|
||||
std::shared_ptr<Module> module;
|
||||
std::vector<std::shared_ptr<Module>> modules;
|
||||
|
||||
std::cout << "\t.text\n\t.align 2\n";
|
||||
|
||||
@@ -206,12 +290,10 @@ int main(int argc, char* argv[])
|
||||
if(verbose)
|
||||
std::cerr << "Module " << name << "(" << segment << "), flags = " << flags << "\n";
|
||||
|
||||
if(module)
|
||||
module->write(std::cout);
|
||||
|
||||
module.reset(new Module());
|
||||
module->name = name;
|
||||
module->labels[0].push_back(name);
|
||||
modules.push_back(module);
|
||||
}
|
||||
break;
|
||||
case kContent:
|
||||
@@ -311,14 +393,15 @@ int main(int argc, char* argv[])
|
||||
case kLast:
|
||||
byte(in);
|
||||
endOfObject = true;
|
||||
if(module)
|
||||
module->write(std::cout);
|
||||
break;
|
||||
default:
|
||||
std::cerr << "Unknown record (type " << recordType << ") at " << std::hex << in.tellg() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(shouldSortModules)
|
||||
sortModules(modules);
|
||||
for(auto& m : modules)
|
||||
m->write(std::cout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
# Copyright 2017 Wolfgang Thaller.
|
||||
#
|
||||
# This file is part of Retro68.
|
||||
#
|
||||
# Retro68 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
find_package(Boost COMPONENTS REQUIRED)
|
||||
|
||||
add_executable(Elf2Mac
|
||||
Elf2Mac.h Elf2Mac.cc SegmentMap.cc LdScript.cc
|
||||
Reloc.h Reloc.cc
|
||||
Symbol.h Symbol.cc
|
||||
Symtab.h Symtab.cc
|
||||
Section.h Section.cc
|
||||
Object.h Object.cc)
|
||||
target_link_libraries(Elf2Mac ResourceFiles ELF)
|
||||
|
||||
target_include_directories(Elf2Mac PRIVATE ${CMAKE_INSTALL_PREFIX}/include)
|
||||
target_include_directories(Elf2Mac PRIVATE ${Boost_INCLUDE_DIR})
|
||||
|
||||
install(TARGETS Elf2Mac RUNTIME DESTINATION bin)
|
||||
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Elf2Mac.h"
|
||||
#include "SegmentMap.h"
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#include <err.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
|
||||
#include "Object.h"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::ofstream;
|
||||
|
||||
string argvZero;
|
||||
|
||||
void RealLD(vector<string> args)
|
||||
{
|
||||
vector<const char*> argv;
|
||||
string realLD = argvZero + ".real";
|
||||
argv.push_back(realLD.c_str());
|
||||
for(string& s : args)
|
||||
argv.push_back(s.c_str());
|
||||
argv.push_back(NULL);
|
||||
|
||||
pid_t pid = fork();
|
||||
if(pid < 0)
|
||||
{
|
||||
perror("unable to fork");
|
||||
exit(-1);
|
||||
}
|
||||
else if(pid == 0)
|
||||
{
|
||||
execvp(argv[0], const_cast<char* const *> (argv.data()));
|
||||
perror("exec failed");
|
||||
exit(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int wstatus;
|
||||
int result = 0;
|
||||
do
|
||||
{
|
||||
result = waitpid(pid, &wstatus, 0);
|
||||
} while(result == -1 && errno == EINTR);
|
||||
if(!WIFEXITED(wstatus))
|
||||
{
|
||||
errx(EXIT_FAILURE, "ld process did not exit properly");
|
||||
}
|
||||
else
|
||||
{
|
||||
int exitcode = WEXITSTATUS(wstatus);
|
||||
if(exitcode)
|
||||
exit(exitcode);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
vector<string> args;
|
||||
std::copy(argv + 1, argv+argc, std::back_inserter(args));
|
||||
argvZero = argv[0];
|
||||
|
||||
if(boost::algorithm::ends_with(argv[0], "ld"))
|
||||
{
|
||||
string outputFile = "a.out";
|
||||
bool elf2mac = false;
|
||||
bool flatoutput = false;
|
||||
bool segments = true;
|
||||
bool stripMacsbug = false;
|
||||
|
||||
vector<string> args2;
|
||||
for(auto p = args.begin(), e = args.end(); p != e; ++p)
|
||||
{
|
||||
if(*p == "-o")
|
||||
{
|
||||
++p;
|
||||
if(p == e)
|
||||
errx(EXIT_FAILURE, "-o missing argument");
|
||||
outputFile = *p;
|
||||
}
|
||||
else if(boost::algorithm::starts_with(*p, "-o"))
|
||||
{
|
||||
outputFile = (*p).substr(2);
|
||||
}
|
||||
else if(*p == "-elf2mac")
|
||||
{
|
||||
elf2mac = true;
|
||||
}
|
||||
else if(*p == "--mac-flat")
|
||||
{
|
||||
elf2mac = true;
|
||||
flatoutput = true;
|
||||
segments = false;
|
||||
}
|
||||
else if(*p == "--mac-single")
|
||||
{
|
||||
elf2mac = true;
|
||||
flatoutput = false;
|
||||
segments = false;
|
||||
}
|
||||
else if(*p == "--mac-segments")
|
||||
{
|
||||
elf2mac = true;
|
||||
if(flatoutput)
|
||||
errx(EXIT_FAILURE, "--mac-segments can't be used with --mac-flat");
|
||||
++p;
|
||||
if(p == e)
|
||||
errx(EXIT_FAILURE, "--mac-segments missing argument");
|
||||
//segmentMapFile = *p;
|
||||
}
|
||||
else if(*p == "--mac-strip-macsbug")
|
||||
{
|
||||
stripMacsbug = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
args2.push_back(*p);
|
||||
}
|
||||
}
|
||||
|
||||
if(elf2mac)
|
||||
{
|
||||
char tmpfile[] = "/tmp/ldscriptXXXXXX";
|
||||
int fd = mkstemp(tmpfile);
|
||||
if(fd < 0)
|
||||
errx(EXIT_FAILURE, "can't create temp file");
|
||||
|
||||
SegmentMap segmentMap;
|
||||
{
|
||||
ofstream out(tmpfile);
|
||||
if(segments)
|
||||
{
|
||||
segmentMap.CreateLdScript(out, stripMacsbug);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateFlatLdScript(out, stripMacsbug);
|
||||
}
|
||||
}
|
||||
|
||||
args2.push_back("-o");
|
||||
args2.push_back(outputFile + ".gdb");
|
||||
args2.push_back("-T");
|
||||
args2.push_back(tmpfile);
|
||||
RealLD(args2);
|
||||
unlink(tmpfile);
|
||||
Object theObject(outputFile + ".gdb");
|
||||
if(flatoutput)
|
||||
theObject.FlatCode(outputFile);
|
||||
else if(segments)
|
||||
theObject.MultiSegmentApp(outputFile, segmentMap);
|
||||
else
|
||||
theObject.SingleSegmentApp(outputFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
RealLD(args);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(argc != 2)
|
||||
errx(EXIT_FAILURE, "usage : %s file-name ", argv[0]);
|
||||
Object theObject(argv[1]);
|
||||
SegmentMap segmentMap;
|
||||
theObject.MultiSegmentApp("out.bin", segmentMap);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef ELF2MAC_H
|
||||
#define ELF2MAC_H
|
||||
|
||||
#include <iosfwd>
|
||||
|
||||
void CreateFlatLdScript(std::ostream& out, bool stripMacsbug);
|
||||
|
||||
#endif // ELF2MAC_H
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Elf2Mac.h"
|
||||
#include "SegmentMap.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/algorithm/string/replace.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <string>
|
||||
|
||||
using std::string;
|
||||
|
||||
const char * scriptStart = R"ld(/* ld script for Elf2Mac */
|
||||
ENTRY( _start )
|
||||
SECTIONS
|
||||
{
|
||||
)ld";
|
||||
|
||||
const char * textSection = R"ld(/* ld script for Elf2Mac */
|
||||
.text : {
|
||||
_stext = . ;
|
||||
PROVIDE(_rsrc_start = .);
|
||||
*(.rsrcheader)
|
||||
. = ALIGN (2);
|
||||
|
||||
/* The entry point. */
|
||||
_entry_trampoline = .;
|
||||
SHORT(DEFINED(__break_on_entry) ? 0xA9FF : 0x4e71);
|
||||
LONG(0x61000002); /* bsr *+2 */
|
||||
SHORT(0x0697); /* addi.l #_, (a7) */
|
||||
LONG(_start - _entry_trampoline - 6);
|
||||
|
||||
PROVIDE(_start = .); /* fallback entry point to a safe spot - needed for libretro bootstrap */
|
||||
Retro68InitMultisegApp = .; /* override this for the single-segment case */
|
||||
SHORT(0x4e75); /* rts */
|
||||
|
||||
*(.relocvars)
|
||||
*/libretrocrt.a:start.c.obj(.text*)
|
||||
*/libretrocrt.a:relocate.c.obj(.text*)
|
||||
*/libretrocrt.a:*(.text*)
|
||||
*(.text*)
|
||||
|
||||
*(.stub)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.glue_7t)
|
||||
*(.glue_7)
|
||||
*(.jcr)
|
||||
. = ALIGN (4) ;
|
||||
__init_section = . ;
|
||||
KEEP (*(.init))
|
||||
__init_section_end = . ;
|
||||
__fini_section = . ;
|
||||
KEEP (*(.fini))
|
||||
__fini_section_end = . ;
|
||||
|
||||
__EH_FRAME_BEGIN__ = .;
|
||||
KEEP(*(.eh_frame))
|
||||
LONG(0);
|
||||
|
||||
KEEP(*(.gcc_except_table))
|
||||
KEEP(*(.gcc_except_table.*))
|
||||
|
||||
/* NOTE: Elf2Mac expects the sections to be contiguous,
|
||||
so include the alignment before the end of this section.
|
||||
*/
|
||||
. = ALIGN(0x4) ;
|
||||
_etext = . ;
|
||||
}
|
||||
)ld";
|
||||
|
||||
const char * scriptEnd = R"ld(
|
||||
.data : {
|
||||
_sdata = . ;
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
FILL(0) ;
|
||||
. = ALIGN(0x20) ;
|
||||
LONG(-1)
|
||||
. = ALIGN(0x20) ;
|
||||
*(.rodata)
|
||||
*(.rodata1)
|
||||
*(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
|
||||
. = ALIGN(4) ;
|
||||
__CTOR_LIST__ = .;
|
||||
KEEP (*(.ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
__CTOR_END__ = .;
|
||||
LONG(0);
|
||||
|
||||
. = ALIGN(0x4);
|
||||
__DTOR_LIST__ = .;
|
||||
KEEP (*(.dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
__DTOR_END__ = .;
|
||||
LONG(0);
|
||||
|
||||
. = ALIGN(0x4);
|
||||
_edata = . ;
|
||||
}
|
||||
.bss ALIGN(0x4) : {
|
||||
_sbss = .;
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.bss*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(0x10) ;
|
||||
_ebss = . ;
|
||||
}
|
||||
|
||||
|
||||
/* **** Debugging information sections.
|
||||
* Keep them for now, they are discarded by Elf2Mac. */
|
||||
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
|
||||
/DISCARD/ : { *(*) }
|
||||
}
|
||||
|
||||
)ld";
|
||||
|
||||
|
||||
void CreateFlatLdScript(std::ostream& out, bool stripMacsbug)
|
||||
{
|
||||
out << "_MULTISEG_APP = 0;\n";
|
||||
out << scriptStart;
|
||||
if(stripMacsbug)
|
||||
{
|
||||
out << "\t.strippedmacsbugnames 0 (NOLOAD) : { *(.text.*.macsbug) }\n";
|
||||
out << "\t. = 0;\n";
|
||||
}
|
||||
out << textSection << scriptEnd;
|
||||
}
|
||||
|
||||
|
||||
void SegmentInfo::WriteFilters(std::ostream &out, string section)
|
||||
{
|
||||
for(string filter : filters)
|
||||
{
|
||||
out << " " << filter << "(" << section << ")\n";
|
||||
out << " " << filter << "(" << section << ".*)\n";
|
||||
}
|
||||
}
|
||||
void SegmentInfo::WriteFiltersKeep(std::ostream &out, string section)
|
||||
{
|
||||
for(string filter : filters)
|
||||
{
|
||||
out << "\t\tKEEP(" << filter << "(" << section << "))\n";
|
||||
out << "\t\tKEEP(" << filter << "(" << section << ".*))\n";
|
||||
}
|
||||
}
|
||||
|
||||
void SegmentInfo::CreateLdScript(std::ostream &out)
|
||||
{
|
||||
out << "\t.code" << id << " : {\n";
|
||||
out << "\t\tFILL(0x4E71);\n";
|
||||
if(id == 1)
|
||||
{
|
||||
out << R"ld(
|
||||
_stext = .;
|
||||
FILL(0x4E71);
|
||||
PROVIDE(_rsrc_start = .);
|
||||
. = ALIGN (2);
|
||||
_entry_trampoline = .;
|
||||
SHORT(DEFINED(__break_on_entry) ? 0xA9FF : 0x4e71);
|
||||
LONG(0x61000002); /* bsr *+2 */
|
||||
SHORT(0x0697); /* addi.l #_, (a7) */
|
||||
LONG(_start - _entry_trampoline - 6);
|
||||
PROVIDE(_start = .); /* fallback entry point to a safe spot - needed for libretro bootstrap */
|
||||
SHORT(0x4e75); /* rts */
|
||||
|
||||
FILL(0);
|
||||
*(.relocvars)
|
||||
FILL(0x4E71);
|
||||
)ld";
|
||||
}
|
||||
WriteFilters(out, ".text");
|
||||
|
||||
if(id == 2)
|
||||
{
|
||||
out << "\t\t*(.gnu.linkonce.t*)\n";
|
||||
}
|
||||
if(id == 1)
|
||||
{
|
||||
out << R"ld(
|
||||
. = ALIGN (4) ;
|
||||
__init_section = .;
|
||||
KEEP (*(.init))
|
||||
__init_section_end = .;
|
||||
__fini_section = .;
|
||||
KEEP (*(.fini))
|
||||
__fini_section_end = .;
|
||||
)ld";
|
||||
}
|
||||
|
||||
out << "\t\t. = ALIGN (4);\n"; // this is important, for some reason.
|
||||
if(id == 1)
|
||||
out << "\t\t__EH_FRAME_BEGIN__" << " = .;\n";
|
||||
else
|
||||
out << "\t\t__EH_FRAME_BEGIN__" << id << " = .;\n";
|
||||
WriteFiltersKeep(out, ".eh_frame");
|
||||
out << "\t\tLONG(0);\n";
|
||||
WriteFiltersKeep(out, ".gcc_except_table");
|
||||
|
||||
if(id == 1)
|
||||
{
|
||||
out << R"ld(
|
||||
. = ALIGN(0x4) ;
|
||||
_etext = . ;
|
||||
)ld";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << boost::replace_all_copy<string>(R"ld(
|
||||
. = ALIGN(0x4);
|
||||
FILL(0);
|
||||
. += 32;
|
||||
LONG(__EH_FRAME_BEGIN__@N@ - .);
|
||||
)ld", "@N@", boost::lexical_cast<string>(id));
|
||||
}
|
||||
|
||||
out << "\t}\n";
|
||||
|
||||
}
|
||||
|
||||
void SegmentMap::CreateLdScript(std::ostream &out, bool stripMacsbug)
|
||||
{
|
||||
out << "_MULTISEG_APP = 1;\n";
|
||||
out << scriptStart;
|
||||
if(stripMacsbug)
|
||||
{
|
||||
out << "\t.strippedmacsbugnames 0 (NOLOAD) : { *(.text.*.macsbug) }\n";
|
||||
out << "\t. = 0;\n";
|
||||
}
|
||||
for(SegmentInfo& seg: segments)
|
||||
{
|
||||
seg.CreateLdScript(out);
|
||||
}
|
||||
|
||||
out << scriptEnd;
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Object.h"
|
||||
#include "Symbol.h"
|
||||
#include "Symtab.h"
|
||||
#include "Section.h"
|
||||
#include "SegmentMap.h"
|
||||
#include "Reloc.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include "ResourceFork.h"
|
||||
#include "BinaryIO.h"
|
||||
#include "ResourceFile.h"
|
||||
|
||||
using std::string;
|
||||
using std::shared_ptr;
|
||||
using std::make_shared;
|
||||
using std::ofstream;
|
||||
using std::unordered_map;
|
||||
using std::vector;
|
||||
|
||||
Object::~Object()
|
||||
{
|
||||
}
|
||||
|
||||
Object::Object(string input)
|
||||
{
|
||||
if(elf_version ( EV_CURRENT ) == EV_NONE)
|
||||
errx(EXIT_FAILURE , "ELF library initialization failed: %s", elf_errmsg( -1));
|
||||
|
||||
int fd = open(input.c_str(), O_RDONLY, 0);
|
||||
elf = elf_begin(fd, ELF_C_READ, NULL);
|
||||
|
||||
elf_getshdrstrndx(elf, §ionHeaderStringTableIdx);
|
||||
|
||||
GElf_Ehdr ehdr;
|
||||
gelf_getehdr(elf, &ehdr);
|
||||
|
||||
int idx;
|
||||
|
||||
idx = 1;
|
||||
for(Elf_Scn *scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; idx++)
|
||||
{
|
||||
GElf_Shdr shdr;
|
||||
gelf_getshdr(scn, &shdr);
|
||||
std::string name = elf_strptr(elf, sectionHeaderStringTableIdx, shdr.sh_name);
|
||||
if(shdr.sh_type == SHT_STRTAB)
|
||||
{
|
||||
if(name == ".strtab")
|
||||
mainStringTableIdx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
idx = 1;
|
||||
for(Elf_Scn *scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; idx++)
|
||||
{
|
||||
GElf_Shdr shdr;
|
||||
gelf_getshdr(scn, &shdr);
|
||||
std::string name = elf_strptr(elf, sectionHeaderStringTableIdx, shdr.sh_name);
|
||||
//std::cout << "section #" << idx << ": " << name << std::endl;
|
||||
//std::cout << " =" << shdr.sh_addr << " + " << shdr.sh_size << std::endl;
|
||||
|
||||
if(shdr.sh_type == SHT_SYMTAB
|
||||
&& !symtab)
|
||||
{
|
||||
symtab.reset(new Symtab(*this, scn));
|
||||
}
|
||||
if(shdr.sh_type == SHT_RELA)
|
||||
{
|
||||
if(boost::algorithm::starts_with(name,".rela."))
|
||||
{
|
||||
string progbitsName = name.substr(5);
|
||||
assert(sections.find(progbitsName) != sections.end());
|
||||
sections[progbitsName]->SetRela(scn);
|
||||
}
|
||||
}
|
||||
if(shdr.sh_type == SHT_PROGBITS && (shdr.sh_flags & SHF_ALLOC))
|
||||
{
|
||||
SectionKind kind = SectionKind::code;
|
||||
|
||||
if(name == ".data")
|
||||
kind = SectionKind::data;
|
||||
if(name == ".strippedmacsbugnames")
|
||||
kind = SectionKind::undefined;
|
||||
|
||||
auto section = make_shared<Section>(*this, name, idx, kind, scn);
|
||||
|
||||
sections[name] = sectionsByElfIndex[idx] = section;
|
||||
if(kind == SectionKind::data)
|
||||
dataSection = section;
|
||||
else if(kind == SectionKind::code)
|
||||
codeSections.push_back(section);
|
||||
}
|
||||
if(shdr.sh_type == SHT_NOBITS)
|
||||
{
|
||||
bssSection = sections[name] = sectionsByElfIndex[idx] =
|
||||
make_shared<Section>(*this, name, idx, SectionKind::bss, scn);
|
||||
}
|
||||
}
|
||||
|
||||
std::sort(codeSections.begin(), codeSections.end(),
|
||||
[](shared_ptr<Section> a, shared_ptr<Section> b) { return a->name < b->name; });
|
||||
}
|
||||
|
||||
void Object::FlatCode(std::ostream& out)
|
||||
{
|
||||
for(auto sec : codeSections)
|
||||
out << sec->GetData();
|
||||
|
||||
out << dataSection->GetData();
|
||||
|
||||
std::vector<RuntimeReloc> relocs;
|
||||
for(auto sec : codeSections)
|
||||
{
|
||||
auto tmp = sec->GetRelocations(false);
|
||||
relocs.insert(relocs.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
{
|
||||
auto tmp = dataSection->GetRelocations(false);
|
||||
relocs.insert(relocs.end(), tmp.begin(), tmp.end());
|
||||
}
|
||||
out << SerializeRelocs(relocs);
|
||||
}
|
||||
|
||||
void Object::FlatCode(string fn)
|
||||
{
|
||||
ofstream out(fn);
|
||||
FlatCode(out);
|
||||
}
|
||||
|
||||
|
||||
std::string fromhex(std::string hex)
|
||||
{
|
||||
std::string bin;
|
||||
int nibble;
|
||||
bool haveNibble = false;
|
||||
for(std::string::iterator p = hex.begin(); p != hex.end(); ++p)
|
||||
{
|
||||
if(std::isspace(*p))
|
||||
continue;
|
||||
assert(isdigit(*p) || (tolower(*p) >= 'a' && tolower(*p) <= 'f'));
|
||||
int digit;
|
||||
if(isdigit(*p))
|
||||
digit = *p - '0';
|
||||
else
|
||||
digit = tolower(*p) - 'a' + 0xA;
|
||||
|
||||
if(haveNibble)
|
||||
{
|
||||
bin += (char) ((nibble << 4) | digit);
|
||||
haveNibble = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
nibble = digit;
|
||||
haveNibble = true;
|
||||
}
|
||||
}
|
||||
return bin;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Object::SingleSegmentApp(string output)
|
||||
{
|
||||
ResourceFile file(output);
|
||||
Resources& rsrc = file.resources;
|
||||
|
||||
rsrc.addResource(Resource(ResType("CODE"), 0,
|
||||
fromhex(
|
||||
"00000028 00000000 00000008 00000020"
|
||||
"0000 3F3C 0001 A9F0"
|
||||
)
|
||||
));
|
||||
|
||||
|
||||
{
|
||||
std::ostringstream code1;
|
||||
word(code1, 0);
|
||||
word(code1, 1);
|
||||
FlatCode(code1);
|
||||
|
||||
rsrc.addResource(Resource(ResType("CODE"), 1,
|
||||
code1.str()));
|
||||
}
|
||||
|
||||
file.creator = ResType("????");
|
||||
file.type = ResType("APPL");
|
||||
|
||||
file.write();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Object::MultiSegmentApp(string output, SegmentMap& segmentMap)
|
||||
{
|
||||
ResourceFile file(output);
|
||||
Resources& rsrc = file.resources;
|
||||
|
||||
for(auto namedSec : sections)
|
||||
{
|
||||
namedSec.second->ScanRelocs();
|
||||
}
|
||||
|
||||
int jtEntryCount = 0;
|
||||
unordered_map<int, vector<Symbol*>> jtEntries;
|
||||
for(Symbol& sym : symtab->symbols)
|
||||
{
|
||||
if(sym.valid)
|
||||
{
|
||||
if(sym.referencedExternally && sym.sectionKind == SectionKind::code)
|
||||
{
|
||||
sym.needsJT = true;
|
||||
sym.jtIndex = -1;
|
||||
sym.section->jtEntries.push_back(&sym);
|
||||
++jtEntryCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t data_and_bss_size = dataSection->shdr.sh_size + bssSection->shdr.sh_size;
|
||||
|
||||
{
|
||||
std::ostringstream code0;
|
||||
longword(code0, 0x20 + 8 * (jtEntryCount+2));
|
||||
longword(code0, data_and_bss_size);
|
||||
longword(code0, 8 * (jtEntryCount+2));
|
||||
longword(code0, 0x20);
|
||||
|
||||
code0 << fromhex("0000 3F3C 0001 A9F0"); // jt entry for entrypoint
|
||||
code0 << fromhex("0000 FFFF 0000 0000"); // 32-bit entries start from here
|
||||
|
||||
int jtIndex = 2;
|
||||
int id = 1;
|
||||
for(auto sec : codeSections)
|
||||
{
|
||||
sec->codeID = id;
|
||||
|
||||
sec->firstJTEntryIndex = jtIndex;
|
||||
|
||||
GElf_Shdr &shdr = sec->shdr;
|
||||
|
||||
for(Symbol* jtEntry : sec->jtEntries)
|
||||
{
|
||||
word(code0, id);
|
||||
word(code0, 0xA9F0);
|
||||
uint32_t offset = jtEntry->st_value - shdr.sh_addr;
|
||||
if(id == 1)
|
||||
offset += 4;
|
||||
else
|
||||
offset += 40;
|
||||
longword(code0, offset);
|
||||
|
||||
jtEntry->jtIndex = jtIndex++;
|
||||
|
||||
//std::cout << "JT Entry " << jtEntry->jtIndex << ": " << jtEntry->name << std::endl;
|
||||
}
|
||||
|
||||
id++;
|
||||
}
|
||||
|
||||
std::cout << "CODE 0: " << code0.str().size() << " bytes\n";
|
||||
std::cout << "above A5: " << 0x20 + 8 * (jtEntryCount+2) << " bytes\n";
|
||||
std::cout << "below A5: " << data_and_bss_size << " bytes\n";
|
||||
std::cout << ".data: " << dataSection->shdr.sh_size << " bytes at A5-"
|
||||
<< std::hex << data_and_bss_size << std::dec << "\n";
|
||||
std::cout << ".bss: " << bssSection->shdr.sh_size << " bytes at A5-"
|
||||
<< std::hex << bssSection->shdr.sh_size << std::dec << "\n";
|
||||
|
||||
rsrc.addResource(Resource(ResType("CODE"), 0, code0.str()));
|
||||
}
|
||||
|
||||
for(auto sec : codeSections)
|
||||
{
|
||||
int id = sec->codeID;
|
||||
if(id == 1)
|
||||
sec->outputBase = 4; // standard 'CODE' header
|
||||
else
|
||||
sec->outputBase = 40; // far-model 'CODE' header
|
||||
|
||||
string exceptionInfoMarker = "__EH_FRAME_BEGIN__";
|
||||
if(id != 1)
|
||||
exceptionInfoMarker += boost::lexical_cast<string>(id);
|
||||
int exceptionInfoSym = symtab->FindSym(exceptionInfoMarker);
|
||||
if(exceptionInfoSym != -1)
|
||||
{
|
||||
Symbol& s = symtab->GetSym(exceptionInfoSym);
|
||||
sec->exceptionInfoStart = s.st_value;
|
||||
|
||||
int codeSize = sec->shdr.sh_size;
|
||||
int exceptionSize = sec->shdr.sh_addr + codeSize - sec->exceptionInfoStart;
|
||||
double percent = 100.0 * exceptionSize / codeSize;
|
||||
|
||||
std::cout << "CODE " << id << " has " << exceptionSize << " bytes of exception info (" << percent << "%)\n";
|
||||
}
|
||||
else
|
||||
std::cout << "exception info marker not found: " << exceptionInfoMarker << std::endl;
|
||||
}
|
||||
dataSection->outputBase = -data_and_bss_size;
|
||||
bssSection->outputBase = -bssSection->shdr.sh_size;
|
||||
|
||||
|
||||
for(auto namedSec : sections)
|
||||
{
|
||||
namedSec.second->FixRelocs();
|
||||
}
|
||||
|
||||
for(auto sec : codeSections)
|
||||
{
|
||||
int id = sec->codeID;
|
||||
std::ostringstream code;
|
||||
if(id == 1)
|
||||
{
|
||||
word(code, 0);
|
||||
word(code, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
word(code, 0xFFFF);
|
||||
word(code, 0);
|
||||
longword(code, 0);
|
||||
longword(code, 0);
|
||||
longword(code, 8 * sec->firstJTEntryIndex );
|
||||
longword(code, sec->jtEntries.size());
|
||||
longword(code, 0); // reloc info for A5
|
||||
longword(code, 0); // assumed address for A5
|
||||
longword(code, 0); // reloc info for code
|
||||
longword(code, 0); // assumed address for start of code resource
|
||||
longword(code, 0);
|
||||
}
|
||||
code << sec->GetData();
|
||||
|
||||
std::cout << "CODE " << id << ": " << code.str().size() << " bytes\n";
|
||||
|
||||
if(code.str().size() == 80)
|
||||
{
|
||||
std::cout << "... empty. Skipping.\n";
|
||||
continue;
|
||||
}
|
||||
|
||||
string segmentName = segmentMap.GetSegmentName(id);
|
||||
|
||||
rsrc.addResource(Resource(ResType("CODE"), id,
|
||||
code.str(),
|
||||
segmentName));
|
||||
|
||||
|
||||
rsrc.addResource(Resource(ResType("RELA"),id, SerializeRelocs(sec->GetRelocations(true))));
|
||||
}
|
||||
|
||||
rsrc.addResource(Resource(ResType("DATA"),0, dataSection->GetData()));
|
||||
rsrc.addResource(Resource(ResType("RELA"),0, SerializeRelocs(dataSection->GetRelocations(true))));
|
||||
|
||||
std::cout << "DATA 0: " << dataSection->shdr.sh_size << " bytes\n";
|
||||
|
||||
file.creator = ResType("????");
|
||||
file.type = ResType("APPL");
|
||||
|
||||
file.write();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef OBJECT_H
|
||||
#define OBJECT_H
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <stdlib.h>
|
||||
#include <iosfwd>
|
||||
|
||||
class Symtab;
|
||||
class Section;
|
||||
class SegmentMap;
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
Elf *elf;
|
||||
std::unique_ptr<Symtab> symtab;
|
||||
std::unordered_map<std::string, std::shared_ptr<Section>> sections;
|
||||
std::unordered_map<int, std::shared_ptr<Section>> sectionsByElfIndex;
|
||||
|
||||
std::vector<std::shared_ptr<Section>> codeSections;
|
||||
std::shared_ptr<Section> dataSection, bssSection;
|
||||
size_t sectionHeaderStringTableIdx;
|
||||
size_t mainStringTableIdx;
|
||||
|
||||
|
||||
Object(std::string input);
|
||||
~Object();
|
||||
|
||||
void FlatCode(std::ostream& out);
|
||||
void FlatCode(std::string fn);
|
||||
|
||||
void SingleSegmentApp(std::string output);
|
||||
void MultiSegmentApp(std::string output, SegmentMap &segmentMap);
|
||||
};
|
||||
|
||||
|
||||
#endif // OBJECT_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Reloc.h"
|
||||
#include <sstream>
|
||||
#include "BinaryIO.h"
|
||||
|
||||
Reloc::Reloc()
|
||||
{
|
||||
}
|
||||
|
||||
Reloc::Reloc(const GElf_Rela &rela)
|
||||
: GElf_Rela(rela), relocBase(RelocBase::code)
|
||||
{
|
||||
}
|
||||
|
||||
std::string SerializeRelocsUncompressed(std::vector<RuntimeReloc> relocs)
|
||||
{
|
||||
std::ostringstream out;
|
||||
for(const auto& r : relocs)
|
||||
{
|
||||
longword(out, r.offset | ((int)r.base << 24));
|
||||
}
|
||||
longword(out, -1);
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::string SerializeRelocs(std::vector<RuntimeReloc> relocs)
|
||||
{
|
||||
std::ostringstream out;
|
||||
uint32_t offset = -1;
|
||||
|
||||
for(const auto& r : relocs)
|
||||
{
|
||||
uint32_t delta = r.offset - offset;
|
||||
offset = r.offset;
|
||||
|
||||
uint32_t base = (uint32_t) r.base;
|
||||
|
||||
uint32_t encoded = (delta << 2) | base;
|
||||
|
||||
while(encoded >= 128)
|
||||
{
|
||||
byte(out, (encoded & 0x7F) | 0x80);
|
||||
encoded >>= 7;
|
||||
}
|
||||
byte(out, encoded);
|
||||
}
|
||||
|
||||
byte(out, 0);
|
||||
|
||||
return out.str();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef RELOC_H
|
||||
#define RELOC_H
|
||||
|
||||
#include <gelf.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
enum class RelocBase
|
||||
{
|
||||
code = 0,
|
||||
data,
|
||||
bss,
|
||||
jumptable,
|
||||
code1
|
||||
};
|
||||
|
||||
class Reloc : public GElf_Rela
|
||||
{
|
||||
public:
|
||||
RelocBase relocBase;
|
||||
|
||||
Reloc();
|
||||
Reloc(const GElf_Rela& rela);
|
||||
};
|
||||
|
||||
class RuntimeReloc
|
||||
{
|
||||
public:
|
||||
RelocBase base;
|
||||
uint32_t offset;
|
||||
|
||||
RuntimeReloc() : base(RelocBase::code), offset(0) {}
|
||||
RuntimeReloc(RelocBase b, uint32_t o) : base(b), offset(o) {}
|
||||
};
|
||||
|
||||
std::string SerializeRelocsUncompressed(std::vector<RuntimeReloc> relocs);
|
||||
std::string SerializeRelocs(std::vector<RuntimeReloc> relocs);
|
||||
|
||||
#endif // RELOC_H
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Section.h"
|
||||
|
||||
#include "Symbol.h"
|
||||
#include "Reloc.h"
|
||||
#include "Object.h"
|
||||
#include "Symtab.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "BinaryIO.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
Section::~Section()
|
||||
{
|
||||
}
|
||||
|
||||
Section::Section(Object& theObject, string name, int idx, SectionKind kind, Elf_Scn *elfsec)
|
||||
: theObject(theObject),
|
||||
name(name), idx(idx), kind(kind), elfsec(elfsec), relasec(NULL),
|
||||
exceptionInfoStart(0),
|
||||
codeID(-1), firstJTEntryIndex(0)
|
||||
{
|
||||
data = elf_getdata(elfsec, NULL);
|
||||
gelf_getshdr(elfsec, &shdr);
|
||||
outputBase = shdr.sh_addr;
|
||||
}
|
||||
|
||||
|
||||
void Section::SetRela(Elf_Scn *scn)
|
||||
{
|
||||
relasec = scn;
|
||||
GElf_Shdr rshdr;
|
||||
gelf_getshdr(relasec, &rshdr);
|
||||
|
||||
int nRela = rshdr.sh_size / rshdr.sh_entsize;
|
||||
Elf_Data *data = elf_getdata(relasec, NULL);
|
||||
for(int i = 0; i < nRela; i++)
|
||||
{
|
||||
GElf_Rela rela;
|
||||
gelf_getrela(data, i, &rela);
|
||||
|
||||
if(rela.r_offset < shdr.sh_addr || rela.r_offset >= shdr.sh_addr + shdr.sh_size)
|
||||
{
|
||||
// For some reason, there sometimes are relocations beyond the end of the sections
|
||||
// in LD output. That's bad. Let's ignore it.
|
||||
continue;
|
||||
}
|
||||
relocs.push_back(rela);
|
||||
}
|
||||
|
||||
std::sort(relocs.begin(), relocs.end(),
|
||||
[](GElf_Rela& a, GElf_Rela& b) { return a.r_offset < b.r_offset; });
|
||||
}
|
||||
|
||||
uint32_t Section::GetSize()
|
||||
{
|
||||
return data->d_size;
|
||||
}
|
||||
|
||||
string Section::GetData()
|
||||
{
|
||||
return string((char*)data->d_buf, (char*)data->d_buf + data->d_size);
|
||||
}
|
||||
|
||||
std::vector<RuntimeReloc> Section::GetRelocations(bool useOffsets)
|
||||
{
|
||||
std::vector<RuntimeReloc> outRelocs;
|
||||
|
||||
for(auto& rela : relocs)
|
||||
{
|
||||
//printf("rel: %d %d %x %x\n", (int)GELF_R_TYPE(rela.r_info), (int)GELF_R_SYM(rela.r_info), (unsigned)rela.r_addend, (unsigned)rela.r_offset);
|
||||
|
||||
int symidx = GELF_R_SYM(rela.r_info);
|
||||
if(symidx == 0)
|
||||
continue;
|
||||
|
||||
Symbol& sym = theObject.symtab->GetSym(symidx);
|
||||
|
||||
if(sym.st_shndx == SHN_UNDEF || sym.st_shndx >= SHN_LORESERVE)
|
||||
continue;
|
||||
if(sym.sectionKind == SectionKind::undefined)
|
||||
continue;
|
||||
|
||||
if(GELF_R_TYPE(rela.r_info) == R_68K_32)
|
||||
{
|
||||
assert(sym.sectionKind != SectionKind::undefined);
|
||||
|
||||
uint32_t offset = rela.r_offset;
|
||||
if(useOffsets)
|
||||
offset -= shdr.sh_addr;
|
||||
|
||||
//longword(out, offset | ((int)rela.relocBase << 24));
|
||||
outRelocs.emplace_back(rela.relocBase, offset);
|
||||
}
|
||||
}
|
||||
|
||||
return outRelocs;
|
||||
}
|
||||
|
||||
void Section::ScanRelocs()
|
||||
{
|
||||
for(Reloc& rela : relocs)
|
||||
{
|
||||
int symidx = GELF_R_SYM(rela.r_info);
|
||||
if(symidx == 0)
|
||||
continue;
|
||||
|
||||
Symbol *sym = &theObject.symtab->GetSym(symidx);
|
||||
|
||||
if(sym->st_shndx == SHN_UNDEF)
|
||||
continue;
|
||||
|
||||
if(rela.r_addend != 0)
|
||||
{
|
||||
int symidx2 = theObject.symtab->FindSym(sym->st_shndx, sym->st_value + rela.r_addend);
|
||||
if(symidx2 != -1)
|
||||
{
|
||||
sym = &theObject.symtab->GetSym(symidx2);
|
||||
rela.r_addend = 0;
|
||||
rela.r_info = GELF_R_INFO(symidx2, GELF_R_TYPE(rela.r_info));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(sym->st_shndx != idx)
|
||||
sym->referencedExternally = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Section::FixRelocs()
|
||||
{
|
||||
for(Reloc& rela : relocs)
|
||||
{
|
||||
if(GELF_R_TYPE(rela.r_info) != R_68K_32)
|
||||
continue;
|
||||
|
||||
int symidx = GELF_R_SYM(rela.r_info);
|
||||
if(symidx == 0)
|
||||
continue;
|
||||
Symbol& sym = theObject.symtab->GetSym(symidx);
|
||||
|
||||
if(sym.sectionKind == SectionKind::undefined)
|
||||
continue;
|
||||
|
||||
RelocBase relocBase;
|
||||
switch(sym.sectionKind)
|
||||
{
|
||||
case SectionKind::code:
|
||||
relocBase = RelocBase::code;
|
||||
if(sym.needsJT && (exceptionInfoStart == 0 || rela.r_offset < exceptionInfoStart || sym.name == "__gxx_personality_v0"))
|
||||
{
|
||||
if(rela.r_addend == 0)
|
||||
{
|
||||
relocBase = RelocBase::jumptable;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sym.section.get() != this)
|
||||
{
|
||||
std::cerr << "Invalid ref from "
|
||||
<< name << ":" << std::hex << rela.r_offset-shdr.sh_addr << std::dec
|
||||
<< " to " << sym.section->name
|
||||
<< "(" << sym.name << ")"
|
||||
<< "+" << rela.r_offset << std::endl;
|
||||
}
|
||||
assert(sym.section.get() == this);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sym.section.get() != this)
|
||||
{
|
||||
std::cerr << "Invalid ref from "
|
||||
<< name << ":" << std::hex << rela.r_offset-shdr.sh_addr << std::dec
|
||||
<< " to " << sym.section->name
|
||||
<< "(" << sym.name << ")"
|
||||
<< "+" << rela.r_offset << std::endl;
|
||||
std::cerr << "needsJT: " << (sym.needsJT ? "true" : "false") << std::endl;
|
||||
std::cerr << "from addr: " << rela.r_offset << ", exceptionInfoStart: " << exceptionInfoStart << std::endl;
|
||||
|
||||
}
|
||||
assert(sym.section.get() == this);
|
||||
}
|
||||
break;
|
||||
case SectionKind::data:
|
||||
relocBase = RelocBase::data;
|
||||
break;
|
||||
case SectionKind::bss:
|
||||
relocBase = RelocBase::bss;
|
||||
break;
|
||||
}
|
||||
rela.relocBase = relocBase;
|
||||
|
||||
uint8_t *relocand = ((uint8_t*) data->d_buf + rela.r_offset - shdr.sh_addr);
|
||||
|
||||
if(relocBase == RelocBase::jumptable)
|
||||
{
|
||||
uint32_t dst = 0x20 + sym.jtIndex * 8 + 2;
|
||||
relocand[0] = dst >> 24;
|
||||
relocand[1] = dst >> 16;
|
||||
relocand[2] = dst >> 8;
|
||||
relocand[3] = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t orig = (relocand[0] << 24) | (relocand[1] << 16) | (relocand[2] << 8) | relocand[3];
|
||||
uint32_t dst = orig + sym.section->outputBase - sym.section->shdr.sh_addr;
|
||||
relocand[0] = dst >> 24;
|
||||
relocand[1] = dst >> 16;
|
||||
relocand[2] = dst >> 8;
|
||||
relocand[3] = dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SECTION_H
|
||||
#define SECTION_H
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Object;
|
||||
class Reloc;
|
||||
class Symbol;
|
||||
class RuntimeReloc;
|
||||
|
||||
enum class SectionKind
|
||||
{
|
||||
undefined = -1,
|
||||
code = 0,
|
||||
data,
|
||||
bss
|
||||
};
|
||||
|
||||
class Section
|
||||
{
|
||||
public:
|
||||
Object& theObject;
|
||||
std::string name;
|
||||
int idx;
|
||||
SectionKind kind;
|
||||
Elf_Scn *elfsec, *relasec;
|
||||
Elf_Data *data;
|
||||
GElf_Shdr shdr;
|
||||
uint32_t outputBase;
|
||||
uint32_t exceptionInfoStart;
|
||||
|
||||
int codeID;
|
||||
|
||||
std::vector<Reloc> relocs;
|
||||
std::vector<Symbol*> jtEntries;
|
||||
int firstJTEntryIndex;
|
||||
|
||||
Section(Object& object, std::string name, int idx, SectionKind kind, Elf_Scn *elfsec);
|
||||
~Section();
|
||||
void SetRela(Elf_Scn *scn);
|
||||
|
||||
uint32_t GetSize();
|
||||
std::string GetData();
|
||||
std::vector<RuntimeReloc> GetRelocations(bool useOffsets);
|
||||
|
||||
void ScanRelocs();
|
||||
void FixRelocs();
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // SECTION_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SegmentMap.h"
|
||||
|
||||
SegmentInfo::SegmentInfo()
|
||||
{
|
||||
}
|
||||
|
||||
SegmentMap::SegmentMap()
|
||||
{
|
||||
segments.emplace_back(1, "Runtime",
|
||||
"*/libretrocrt.a:start.c.obj",
|
||||
"*/libretrocrt.a:relocate.c.obj",
|
||||
"*/libretrocrt.a:MultiSegApp.c.obj",
|
||||
"*/libretrocrt.a:LoadSeg.s.obj",
|
||||
"*/libretrocrt.a:*",
|
||||
"*/libgcc.a:*",
|
||||
"*/libc.a:*"
|
||||
);
|
||||
segments.emplace_back(5, "libstdc++ locale",
|
||||
"*/libstdc++.a:locale.o",
|
||||
"*/libstdc++.a:locale_faces.o",
|
||||
"*/libstdc++.a:locale_init.o");
|
||||
segments.emplace_back(7, "libstdc++ locale-inst",
|
||||
"*/libstdc++.a:locale-inst.o");
|
||||
segments.emplace_back(8, "libstdc++ wlocale-inst",
|
||||
"*/libstdc++.a:wlocale-inst.o");
|
||||
segments.emplace_back(6, "libstdc++ cp-demangle",
|
||||
"*/libstdc++.a:cp-demangle.o");
|
||||
segments.emplace_back(3, "libstdc++",
|
||||
"*/libstdc++.a:*");
|
||||
segments.emplace_back(4, "RetroConsole",
|
||||
"*/libRetroConsole.a:*");
|
||||
|
||||
segments.emplace_back(2, "Main",
|
||||
"*");
|
||||
}
|
||||
|
||||
std::string SegmentMap::GetSegmentName(int id)
|
||||
{
|
||||
for(auto& seg : segments)
|
||||
{
|
||||
if(seg.id == id)
|
||||
return seg.name;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SEGMENTMAP_H
|
||||
#define SEGMENTMAP_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class SegmentInfo
|
||||
{
|
||||
public:
|
||||
int id;
|
||||
std::string name;
|
||||
std::vector<std::string> filters;
|
||||
SegmentInfo();
|
||||
|
||||
template<typename... Args>
|
||||
SegmentInfo(int id, std::string name, Args... args)
|
||||
: id(id), name(name), filters { args... }
|
||||
{
|
||||
}
|
||||
|
||||
void WriteFilters(std::ostream& out, std::string section);
|
||||
void WriteFiltersKeep(std::ostream& out, std::string section);
|
||||
void CreateLdScript(std::ostream& out);
|
||||
};
|
||||
|
||||
class SegmentMap
|
||||
{
|
||||
std::vector<SegmentInfo> segments;
|
||||
public:
|
||||
SegmentMap();
|
||||
|
||||
void CreateLdScript(std::ostream& out, bool stripMacsbug);
|
||||
std::string GetSegmentName(int id);
|
||||
};
|
||||
|
||||
#endif // SEGMENTMAP_H
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Symbol.h"
|
||||
|
||||
#include "Section.h"
|
||||
#include "Object.h"
|
||||
|
||||
Symbol::Symbol()
|
||||
: valid(false)
|
||||
{
|
||||
}
|
||||
|
||||
Symbol::Symbol(Object& theObject, const GElf_Sym &sym)
|
||||
: GElf_Sym(sym), valid(true),
|
||||
referencedExternally(false),
|
||||
sectionKind(SectionKind::undefined),
|
||||
needsJT(false)
|
||||
{
|
||||
if(st_shndx != SHN_UNDEF && st_shndx < SHN_LORESERVE)
|
||||
{
|
||||
section = theObject.sectionsByElfIndex[st_shndx];
|
||||
sectionKind = section->kind;
|
||||
}
|
||||
if(st_name)
|
||||
{
|
||||
name = elf_strptr(theObject.elf, theObject.mainStringTableIdx, st_name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SYMBOL_H
|
||||
#define SYMBOL_H
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
enum class SectionKind;
|
||||
class Section;
|
||||
class Object;
|
||||
|
||||
class Symbol : public GElf_Sym
|
||||
{
|
||||
public:
|
||||
bool valid;
|
||||
bool referencedExternally;
|
||||
SectionKind sectionKind;
|
||||
bool needsJT;
|
||||
int jtIndex;
|
||||
std::shared_ptr<Section> section;
|
||||
std::string name;
|
||||
|
||||
Symbol();
|
||||
Symbol(Object &theObject, const GElf_Sym& sym);
|
||||
};
|
||||
|
||||
|
||||
#endif // SYMBOL_H
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Symtab.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <utility>
|
||||
|
||||
#include "Symbol.h"
|
||||
|
||||
using std::make_pair;
|
||||
using std::string;
|
||||
|
||||
Symtab::Symtab(Object& theObject, Elf_Scn *elfsec)
|
||||
: elfsec(elfsec)
|
||||
{
|
||||
data = elf_getdata(elfsec, NULL);
|
||||
|
||||
GElf_Shdr shdr;
|
||||
gelf_getshdr(elfsec, &shdr);
|
||||
|
||||
int count = shdr.sh_size / shdr.sh_entsize;
|
||||
symbols.reserve(count);
|
||||
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
GElf_Sym sym;
|
||||
auto res = gelf_getsym(data, i, &sym);
|
||||
assert(res != 0);
|
||||
symbols.emplace_back(theObject, sym);
|
||||
|
||||
if(sym.st_shndx != SHN_UNDEF && sym.st_shndx < SHN_LORESERVE)
|
||||
symbolsByAddress[make_pair((int)sym.st_shndx,sym.st_value)] = i;
|
||||
if(sym.st_name)
|
||||
symbolsByName[symbols.back().name] = i;
|
||||
}
|
||||
}
|
||||
|
||||
Symtab::~Symtab()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Symbol &Symtab::GetSym(int idx)
|
||||
{
|
||||
return symbols[idx];
|
||||
}
|
||||
|
||||
int Symtab::FindSym(int secidx, uint32_t addr)
|
||||
{
|
||||
auto p = symbolsByAddress.find(make_pair(secidx, addr));
|
||||
if(p != symbolsByAddress.end())
|
||||
return p->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Symtab::FindSym(string name)
|
||||
{
|
||||
auto p = symbolsByName.find(name);
|
||||
if(p != symbolsByName.end())
|
||||
return p->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
Copyright 2017 Wolfgang Thaller.
|
||||
|
||||
This file is part of Retro68.
|
||||
|
||||
Retro68 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 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SYMTAB_H
|
||||
#define SYMTAB_H
|
||||
|
||||
#include <gelf.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
class Object;
|
||||
class Symbol;
|
||||
|
||||
class Symtab
|
||||
{
|
||||
public:
|
||||
Elf_Scn *elfsec;
|
||||
Elf_Data *data;
|
||||
std::vector<Symbol> symbols;
|
||||
std::map<std::pair<int,uint32_t>, int> symbolsByAddress;
|
||||
std::unordered_map<std::string, int> symbolsByName;
|
||||
|
||||
Symtab(Object &theObject, Elf_Scn *elfsec);
|
||||
~Symtab();
|
||||
|
||||
Symbol& GetSym(int idx);
|
||||
int FindSym(int secidx, uint32_t addr);
|
||||
int FindSym(std::string name);
|
||||
};
|
||||
|
||||
|
||||
#endif // SYMTAB_H
|
||||
@@ -109,6 +109,7 @@ Sample programs are built in several formats:
|
||||
- Elsewhere: `ApplicationName.APPL`, `.rsrc/ApplicationName.APPL`, `.finf/ApplicationName.APPL` (BasiliskII/Sheepshaver compatible)
|
||||
- MacBinary files (`ApplicationName.bin`)
|
||||
- Raw HFS disk image (`ApplicationName.dsk`, containing `ApplicationName`)
|
||||
- AppleDouble file pairs (`ApplicationName.ad`, `%ApplicationName.ad`, Executor compatible)
|
||||
|
||||
Look under `Retro68-build/build-target/` (68K),
|
||||
`Retro68-build/build-target-ppc/` (PowerPC Classic) and
|
||||
|
||||
@@ -125,6 +125,24 @@ ResourceFile::~ResourceFile()
|
||||
|
||||
}
|
||||
|
||||
static bool CheckAppleDouble(fs::path path, std::string prefix)
|
||||
{
|
||||
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
|
||||
fs::ifstream in(adPath);
|
||||
if(in)
|
||||
{
|
||||
int magic1 = longword(in);
|
||||
|
||||
if(in && magic1 == 0x00051607)
|
||||
{
|
||||
int magic2 = longword(in);
|
||||
if(in && magic2 == 0x00020000)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f)
|
||||
{
|
||||
this->pathstring = pathstring;
|
||||
@@ -140,24 +158,27 @@ bool ResourceFile::assign(std::string pathstring, ResourceFile::Format f)
|
||||
format = Format::macbin;
|
||||
else if(path.extension() == ".dsk" || path.extension() == ".img")
|
||||
format = Format::diskimage;
|
||||
else if(path.filename().string().substr(0,2) == "._")
|
||||
{
|
||||
path = path.parent_path() / path.filename().string().substr(2);
|
||||
format = Format::underscore_appledouble;
|
||||
this->pathstring = path.string();
|
||||
}
|
||||
else if(path.filename().string()[0] == '%')
|
||||
{
|
||||
path = path.parent_path() / path.filename().string().substr(1);
|
||||
format = Format::percent_appledouble;
|
||||
this->pathstring = path.string();
|
||||
}
|
||||
//else if(fs::exists(rsrcPath))
|
||||
// format = Format::basilisk;
|
||||
}
|
||||
if(format == Format::autodetect)
|
||||
{
|
||||
fs::path adPath = path.parent_path() / ("._" + path.filename().string());
|
||||
fs::ifstream in(adPath);
|
||||
if(in)
|
||||
{
|
||||
int magic1 = longword(in);
|
||||
|
||||
if(in && magic1 == 0x00051607)
|
||||
{
|
||||
int magic2 = longword(in);
|
||||
if(in && magic2 == 0x00020000)
|
||||
format = Format::underscore_appledouble;
|
||||
}
|
||||
}
|
||||
if(CheckAppleDouble(path, "._"))
|
||||
format = Format::underscore_appledouble;
|
||||
if(CheckAppleDouble(path, "%"))
|
||||
format = Format::percent_appledouble;
|
||||
}
|
||||
if(format == Format::autodetect)
|
||||
{
|
||||
@@ -264,12 +285,16 @@ bool ResourceFile::read()
|
||||
}
|
||||
break;
|
||||
case Format::underscore_appledouble:
|
||||
case Format::percent_appledouble:
|
||||
{
|
||||
fs::ifstream dataIn(path);
|
||||
data = std::string(std::istreambuf_iterator<char>(dataIn),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
fs::path adPath = path.parent_path() / ("._" + path.filename().string());
|
||||
std::string prefix = format == Format::underscore_appledouble ?
|
||||
"._" : "%";
|
||||
|
||||
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
|
||||
fs::ifstream in(adPath);
|
||||
if(longword(in) != 0x00051607)
|
||||
return false;
|
||||
@@ -404,14 +429,53 @@ bool ResourceFile::write()
|
||||
longword(out, 2);
|
||||
longword(out, rsrcStart);
|
||||
longword(out, finfStart - rsrcStart);
|
||||
longword(out, 3);
|
||||
longword(out, 9);
|
||||
longword(out, finfStart);
|
||||
longword(out, 32);
|
||||
}
|
||||
break;
|
||||
|
||||
// TODO: case Format::underscore_appledouble
|
||||
|
||||
case Format::underscore_appledouble:
|
||||
case Format::percent_appledouble:
|
||||
{
|
||||
fs::ofstream dataOut(path);
|
||||
|
||||
dataOut << data;
|
||||
|
||||
std::string prefix = format == Format::underscore_appledouble ?
|
||||
"._" : "%";
|
||||
|
||||
fs::path adPath = path.parent_path() / (prefix + path.filename().string());
|
||||
|
||||
fs::ofstream out(adPath);
|
||||
|
||||
longword(out, 0x00051607);
|
||||
longword(out, 0x00020000);
|
||||
|
||||
for(int i = 0; i < 16; i++)
|
||||
byte(out, 0);
|
||||
word(out, 2);
|
||||
std::streampos entries = out.tellp();
|
||||
for(int i = 0; i < 2*3; i++)
|
||||
longword(out, 0);
|
||||
std::streampos rsrcStart = out.tellp();
|
||||
resources.writeFork(out);
|
||||
std::streampos finfStart = out.tellp();
|
||||
ostype(out, type);
|
||||
ostype(out, creator);
|
||||
for(int i = 8; i < 32; i++)
|
||||
byte(out, 0);
|
||||
out.seekp(entries);
|
||||
longword(out, 2);
|
||||
longword(out, rsrcStart);
|
||||
longword(out, finfStart - rsrcStart);
|
||||
longword(out, 9);
|
||||
longword(out, finfStart);
|
||||
longword(out, 32);
|
||||
}
|
||||
break;
|
||||
|
||||
case Format::diskimage:
|
||||
{
|
||||
std::ostringstream rsrcOut;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
basilisk,
|
||||
applesingle,
|
||||
underscore_appledouble,
|
||||
//appledouble
|
||||
percent_appledouble
|
||||
};
|
||||
|
||||
ResourceFile();
|
||||
|
||||
@@ -27,3 +27,11 @@ add_application(Dialog
|
||||
dialog.c
|
||||
dialog.r
|
||||
)
|
||||
|
||||
# Enable -ffunction-sections and -gc-sections to make the app as small as possible
|
||||
# also enable --mac-single to build it as a single-segment app (so that this code path doesn't rot)
|
||||
set_target_properties(Dialog
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS -ffunction-sections
|
||||
LINK_FLAGS "-Wl,-gc-sections -Wl,--mac-single"
|
||||
)
|
||||
|
||||
@@ -10,3 +10,13 @@ add_application(HelloWorld
|
||||
hello.c
|
||||
CONSOLE
|
||||
)
|
||||
|
||||
# make the result as small as possible
|
||||
# by removing unused code (gc-sections)
|
||||
# and by removing macsbug function names
|
||||
# (don't do this when debugging...)
|
||||
set_target_properties(HelloWorld
|
||||
PROPERTIES
|
||||
COMPILE_OPTIONS -ffunction-sections
|
||||
LINK_FLAGS "-Wl,-gc-sections -Wl,--mac-strip-macsbug"
|
||||
)
|
||||
|
||||
@@ -1,26 +1,53 @@
|
||||
# Copyright 2017 Wolfgang Thaller.
|
||||
#
|
||||
# This file is part of Retro68.
|
||||
#
|
||||
# Retro68 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Retro68 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 Retro68. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Here's how to build a system extension, a.k.a. an INIT.
|
||||
# The same applies to various other kinds of code resources.
|
||||
|
||||
# PowerPC is not currently supported here.
|
||||
# As for Carbon, there are no code resources anyway.
|
||||
|
||||
# Step 1:
|
||||
# Build the code resource as a regular executable
|
||||
# (not using the add_application macro)
|
||||
add_executable(SystemExtension
|
||||
SystemExtension.c
|
||||
SystemExtension.r
|
||||
ShowInitIcon.c
|
||||
SystemExtension.r
|
||||
ShowInitIcon.h)
|
||||
|
||||
set_target_properties(SystemExtension PROPERTIES OUTPUT_NAME SystemExtension.flt)
|
||||
set_target_properties(SystemExtension PROPERTIES
|
||||
OUTPUT_NAME SystemExtension.flt
|
||||
|
||||
# set a linker flag that says we want a flat piece
|
||||
# of code in a data file
|
||||
LINK_FLAGS -Wl,--mac-flat)
|
||||
|
||||
# Use Rez to put it together
|
||||
add_custom_command(
|
||||
OUTPUT SystemExtension.bin SystemExtension.dsk
|
||||
COMMAND ${REZ} -I ${REZ_INCLUDE_PATH}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/SystemExtension.r
|
||||
--copy ${CMAKE_CURRENT_SOURCE_DIR}/Icons.rsrc.bin
|
||||
-o SystemExtension.bin
|
||||
-t INIT
|
||||
COMMAND ${REZ} --copy SystemExtension.bin
|
||||
-o SystemExtension.dsk
|
||||
-t INIT
|
||||
COMMAND ${REZ} --copy SystemExtension.bin
|
||||
-o SystemExtension
|
||||
--cc SystemExtension.dsk
|
||||
--cc SystemExtension
|
||||
-t INIT
|
||||
DEPENDS SystemExtension SystemExtension.r Icons.rsrc.bin)
|
||||
|
||||
|
||||
|
||||
add_custom_target(SystemExtension_INIT ALL DEPENDS SystemExtension.dsk)
|
||||
|
||||
+30
-12
@@ -18,6 +18,8 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <exception>
|
||||
|
||||
#include <Events.h>
|
||||
|
||||
@@ -30,8 +32,28 @@ void foobar()
|
||||
throw Foo();
|
||||
}
|
||||
|
||||
void UnexpectedExceptionOccurred()
|
||||
{
|
||||
printf("std::unexpected called.\n");
|
||||
printf("Press Enter...\n");
|
||||
getchar();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void UncaughtExceptionOccurred()
|
||||
{
|
||||
printf("std::terminate called.\n");
|
||||
printf("Press Enter...\n");
|
||||
getchar();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
std::set_unexpected(&UnexpectedExceptionOccurred);
|
||||
std::set_terminate(&UncaughtExceptionOccurred);
|
||||
bool throwFail = false;
|
||||
bool catchFail = true;
|
||||
for(int i = 0; i < 5; i++)
|
||||
{
|
||||
int n = i == 0 ? 1 : 100;
|
||||
@@ -39,23 +61,19 @@ int main(int argc, char** argv)
|
||||
long start = TickCount();
|
||||
for(int j = 0; j < n; j++)
|
||||
{
|
||||
try { foobar(); } catch(...) {}
|
||||
try { foobar(); throwFail = true; } catch(...) { catchFail = false; }
|
||||
}
|
||||
long end = TickCount();
|
||||
|
||||
printf("%g ms per throw/catch\n",(end-start)*1000 / 60.0 / n);
|
||||
}
|
||||
|
||||
const int n = 3;
|
||||
printf("Click mouse %d times...\n", n);
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
while(!Button())
|
||||
;
|
||||
while(Button())
|
||||
;
|
||||
printf("Click #%d\n", i+1);
|
||||
}
|
||||
FlushEvents(everyEvent, 0);
|
||||
if(throwFail)
|
||||
printf("******** FAILURE: throw didn't really throw\n");
|
||||
if(catchFail)
|
||||
printf("******** FAILURE: catch block never entered\n");
|
||||
|
||||
printf("Press Enter...\n");
|
||||
getchar();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -12688,6 +12688,23 @@ _bfd_elf_gc_mark (struct bfd_link_info *info,
|
||||
if (!_bfd_elf_gc_mark (info, group_sec, gc_mark_hook))
|
||||
return FALSE;
|
||||
|
||||
{ /* keep macsbug sections */
|
||||
asection *next_sec = sec->next;
|
||||
if(next_sec)
|
||||
{
|
||||
const char *p = sec->name, *q = next_sec->name;
|
||||
|
||||
while(*p && *q && *p == *q)
|
||||
p++, q++;
|
||||
|
||||
if(*p == 0 && strcmp(q, ".macsbug") == 0)
|
||||
if(!next_sec->gc_mark)
|
||||
if (!_bfd_elf_gc_mark (info, next_sec, gc_mark_hook))
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Look through the section relocs. */
|
||||
ret = TRUE;
|
||||
eh_frame = elf_eh_frame_section (sec->owner);
|
||||
|
||||
+8
-21
@@ -104,7 +104,6 @@ if [ $SKIP_THIRDPARTY != false ]; then
|
||||
if [ $BUILD_68K != false ]; then
|
||||
if [ ! -d binutils-build ]; then MISSING=true; fi
|
||||
if [ ! -d gcc-build ]; then MISSING=true; fi
|
||||
if [ ! -d elf2flt-build ]; then MISSING=true; fi
|
||||
fi
|
||||
if [ $BUILD_PPC != false ]; then
|
||||
if [ ! -d binutils-build-ppc ]; then MISSING=true; fi
|
||||
@@ -239,7 +238,7 @@ if [ $BUILD_CARBON != false ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
##################### Third-Party components: binutils, gcc, elf2flt, hfsutils
|
||||
##################### Third-Party components: binutils, gcc, hfsutils
|
||||
|
||||
if [ $SKIP_THIRDPARTY != true ]; then
|
||||
|
||||
@@ -247,7 +246,7 @@ if [ $SKIP_THIRDPARTY != true ]; then
|
||||
rm -rf toolchain
|
||||
mkdir -p toolchain
|
||||
|
||||
# Components needed for targeting 68K: binutils, gcc, elf2flt
|
||||
# Components needed for targeting 68K: binutils, gcc
|
||||
if [ $BUILD_68K != false ]; then
|
||||
|
||||
# present-day Mac users are likely to install dependencies
|
||||
@@ -279,28 +278,16 @@ if [ $SKIP_THIRDPARTY != true ]; then
|
||||
unset CPPFLAGS
|
||||
unset LDFLAGS
|
||||
|
||||
# Install elf.h (for elf2flt)
|
||||
mkdir -p $PREFIX/include
|
||||
cp $SRC/elf.h $PREFIX/include/
|
||||
|
||||
# Build elf2flt
|
||||
export "CFLAGS=-I${SRC}/binutils/include -I../toolchain/include"
|
||||
export "CPPFLAGS=$CFLAGS"
|
||||
mkdir -p elf2flt-build
|
||||
cd elf2flt-build
|
||||
$SRC/elf2flt/configure --target=m68k-apple-macos --prefix=$PREFIX \
|
||||
--with-binutils-build-dir=$BINUTILS
|
||||
make -j8 TOOLDIR=$PREFIX/bin
|
||||
make install
|
||||
cd ..
|
||||
|
||||
unset CFLAGS
|
||||
unset CPPFLAGS
|
||||
# Move the real linker aside and install symlinks to Elf2Mac
|
||||
# (Elf2Mac is built by cmake below)
|
||||
mv $PREFIX/bin/m68k-apple-macos-ld $PREFIX/bin/m68k-apple-macos-ld.real
|
||||
mv $PREFIX/m68k-apple-macos/bin/ld $PREFIX/m68k-apple-macos/bin/ld.real
|
||||
ln -s $PREFIX/bin/Elf2Mac $PREFIX/bin/m68k-apple-macos-ld
|
||||
ln -s $PREFIX/bin/Elf2Mac $PREFIX/m68k-apple-macos/bin/ld
|
||||
|
||||
if [ $CLEAN_AFTER_BUILD != false ]; then
|
||||
rm -rf binutils-build
|
||||
rm -rf gcc-build
|
||||
rm -rf elf2flt-build
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
@@ -43,7 +43,7 @@ function(add_application name)
|
||||
add_executable(${name} ${files} ${rez_files})
|
||||
|
||||
if(${ARGS_DEBUGBREAK})
|
||||
list(APPEND ARGS_MAKEAPPL_ARGS -b)
|
||||
list(APPEND ARGS_MAKEAPPL_ARGS -DBREAK_ON_ENTRY)
|
||||
endif()
|
||||
if(${ARGS_CONSOLE})
|
||||
target_link_libraries(${name} RetroConsole)
|
||||
@@ -70,15 +70,16 @@ function(add_application name)
|
||||
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Retro68)
|
||||
|
||||
set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.flt)
|
||||
set_target_properties(${name} PROPERTIES OUTPUT_NAME ${name}.code.bin)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk
|
||||
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk ${name}.ad "%${name}.ad"
|
||||
COMMAND ${REZ} ${REZ_FLAGS}
|
||||
${REZ_TEMPLATES_PATH}/Retro68APPL.r
|
||||
-I${REZ_INCLUDE_PATH}
|
||||
-DFLT_FILE_NAME="\\"${name}.flt\\""
|
||||
-o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL"
|
||||
--copy "${name}.code.bin"
|
||||
-o "${name}.bin"
|
||||
--cc "${name}.dsk" --cc "${name}.APPL" --cc "%${name}.ad"
|
||||
-t ${ARGS_TYPE} -c ${ARGS_CREATOR}
|
||||
${ARGS_MAKEAPPL_ARGS}
|
||||
DEPENDS ${name} ${rsrc_files})
|
||||
@@ -100,13 +101,14 @@ function(add_application name)
|
||||
DEPENDS ${name})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk
|
||||
OUTPUT ${name}.bin ${name}.APPL ${name}.dsk ${name}.ad "%${name}.ad"
|
||||
COMMAND ${REZ}
|
||||
${REZ_FLAGS}
|
||||
${REZ_TEMPLATE}
|
||||
-I${REZ_INCLUDE_PATH}
|
||||
-DCFRAG_NAME="\\"${name}\\""
|
||||
-o "${name}.bin" --cc "${name}.dsk" --cc "${name}.APPL"
|
||||
--cc "%${name}.ad"
|
||||
-t ${ARGS_TYPE} -c ${ARGS_CREATOR}
|
||||
--data ${name}.pef
|
||||
${ARGS_MAKEAPPL_ARGS}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
# standard patterns
|
||||
*.a
|
||||
*.o
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
*.patch
|
||||
.deps
|
||||
|
||||
a.out
|
||||
*.gdb
|
||||
*.exe
|
||||
|
||||
# autotool files
|
||||
autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
Makefile
|
||||
|
||||
# our generated files
|
||||
elf2flt
|
||||
elf2flt.ld
|
||||
flthdr
|
||||
ld-elf2flt
|
||||
@@ -1,22 +0,0 @@
|
||||
/.gitignore/1.2/Tue Jul 7 00:46:52 2009//
|
||||
/LICENSE.TXT/1.1/Mon Apr 18 22:00:48 2005//
|
||||
/Makefile.in/1.28/Wed Feb 3 22:32:46 2010/-ko/
|
||||
/README/1.6/Wed Jan 20 02:28:18 2010/-ko/
|
||||
/compress.c/1.3/Tue Jul 7 04:39:42 2009//
|
||||
/compress.h/1.2/Sun Nov 2 23:10:52 2008//
|
||||
/config.guess/1.2/Mon Jan 5 23:41:50 2004/-ko/
|
||||
/config.sub/1.8/Wed Jan 11 03:39:16 2006/-ko/
|
||||
/configure/1.21/Wed Feb 3 22:34:49 2010/-ko/
|
||||
/configure.in/1.20/Wed Feb 3 22:34:49 2010/-ko/
|
||||
/cygwin-elf.h/1.4/Wed Jan 11 03:39:16 2006//
|
||||
/e1-elf2flt.ld/1.1/Tue Nov 11 07:23:04 2003//
|
||||
/elf2flt.c/1.64/Wed Feb 3 22:32:46 2010/-ko/
|
||||
/elf2flt.ld.in/1.5/Thu Dec 16 01:37:41 2010//
|
||||
/flat.h/1.8/Mon Jul 6 04:45:16 2009/-ko/
|
||||
/flthdr.c/1.17/Tue Jun 22 06:12:47 2010/-ko/
|
||||
/install-sh/1.1.1.1/Thu Feb 14 01:40:55 2002/-ko/
|
||||
/ld-elf2flt.c/1.6/Mon Apr 4 01:17:17 2011//
|
||||
/ld-elf2flt.in/1.23/Sun Jul 12 23:28:58 2009//
|
||||
/stubs.c/1.4/Sun Jul 12 23:28:58 2009//
|
||||
/stubs.h/1.3/Fri Jan 22 01:54:20 2010//
|
||||
D
|
||||
@@ -1 +0,0 @@
|
||||
elf2flt
|
||||
@@ -1 +0,0 @@
|
||||
:pserver:anonymous@cvs.uclinux.org:/var/cvs
|
||||
@@ -1,114 +0,0 @@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
libdir = @libdir@
|
||||
includedir = @includedir@
|
||||
|
||||
CC = @CC@
|
||||
CPU = @target_cpu@
|
||||
TARGET = @target_alias@
|
||||
SYMBOL_PREFIX = @SYMBOL_PREFIX@
|
||||
CFLAGS = @CFLAGS@
|
||||
INCLUDES = -I$(srcdir) @bfd_include_dir@ @binutils_include_dir@ @zlib_include_dir@
|
||||
CPPFLAGS = @CPPFLAGS@ $(DEFS) $(INCLUDES)
|
||||
LDFLAGS = @LDFLAGS@
|
||||
LDLIBS = @LIBS@
|
||||
INSTALL = @INSTALL@
|
||||
DEFS = @DEFS@ \
|
||||
-DTARGET_$(CPU) \
|
||||
-DTARGET_CPU=\"$(CPU)\" \
|
||||
-DSYMBOL_PREFIX=\"$(SYMBOL_PREFIX)\" \
|
||||
-DBINUTILS_LDSCRIPTDIR=\"@binutils_ldscript_dir@\" \
|
||||
-DTARGET_ALIAS=\"$(TARGET)\" \
|
||||
-DNO_GOT_CHECK=@got_check@ \
|
||||
-DUSE_EMIT_RELOCS=@emit_relocs@ \
|
||||
-DEMIT_CTOR_DTOR=@emit_ctor_dtor@ \
|
||||
-DALWAYS_RELOC_TEXT=@always_reloc_text@
|
||||
EXEEXT = @EXEEXT@
|
||||
OBJEXT = @OBJEXT@
|
||||
|
||||
HOST = @host_alias@
|
||||
|
||||
ifneq (,$(findstring mingw32,$(HOST)))
|
||||
LDLIBS += -lws2_32
|
||||
endif
|
||||
|
||||
# force link order under cygwin to avoid getopts / libiberty clash
|
||||
ifneq ($(strip $(shell gcc -v 2>&1 | grep "cygwin")),)
|
||||
LDLIBS := -lcygwin $(LDLIBS)
|
||||
endif
|
||||
|
||||
LDFILE= elf2flt.ld
|
||||
ifeq ($(strip $(CPU)),e1)
|
||||
SRC_LDFILE= $(srcdir)/$(CPU)-elf2flt.ld
|
||||
else
|
||||
SRC_LDFILE= elf2flt.ld
|
||||
endif
|
||||
|
||||
target_bindir = $(prefix)/$(TARGET)/bin
|
||||
target_libdir = $(prefix)/$(TARGET)/lib
|
||||
|
||||
|
||||
PROG_ELF2FLT = elf2flt$(EXEEXT)
|
||||
PROG_FLTHDR = flthdr$(EXEEXT)
|
||||
PROG_LD_ELF2FLT_C = ld-elf2flt$(EXEEXT)
|
||||
PROG_LD_ELF2FLT_SH = ld-elf2flt.sh
|
||||
|
||||
ifeq (@use_ld_elf2flt_binary@,yes)
|
||||
PROG_LD_ELF2FLT = $(PROG_LD_ELF2FLT_C)
|
||||
else
|
||||
PROG_LD_ELF2FLT = $(PROG_LD_ELF2FLT_SH)
|
||||
endif
|
||||
|
||||
PROGS = $(PROG_ELF2FLT) $(PROG_FLTHDR) $(PROG_LD_ELF2FLT_C) $(PROG_LD_ELF2FLT_SH)
|
||||
|
||||
all: $(PROGS)
|
||||
|
||||
# We need to declare the link explicitly because make only provides
|
||||
# implicit rules when EXEEXT is set to nothing
|
||||
link = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LDLIBS)
|
||||
|
||||
$(PROG_ELF2FLT): elf2flt.o compress.o stubs.o
|
||||
$(link)
|
||||
|
||||
$(PROG_FLTHDR): flthdr.o compress.o stubs.o
|
||||
$(link)
|
||||
|
||||
ld-elf2flt$(EXEEXT): ld-elf2flt.o stubs.o
|
||||
$(link)
|
||||
|
||||
ld-elf2flt.sh: $(srcdir)/ld-elf2flt.in
|
||||
./config.status $@
|
||||
chmod 755 $@
|
||||
|
||||
Makefile: $(srcdir)/Makefile.in
|
||||
./config.status $@
|
||||
|
||||
clean:
|
||||
-rm -f $(PROGS) *.$(OBJEXT) .deps
|
||||
|
||||
distclean: clean
|
||||
-rm -f Makefile config.log config.status config.cache ld-elf2flt
|
||||
|
||||
install:
|
||||
$(INSTALL) -d $(bindir)
|
||||
$(INSTALL) -d $(target_bindir)
|
||||
$(INSTALL) -d $(target_libdir)
|
||||
$(INSTALL) -m 755 $(PROG_FLTHDR) $(bindir)/$(TARGET)-$(PROG_FLTHDR)
|
||||
$(INSTALL) -m 755 $(PROG_FLTHDR) $(target_bindir)/$(PROG_FLTHDR)
|
||||
$(INSTALL) -m 755 $(PROG_ELF2FLT) $(bindir)/$(TARGET)-$(PROG_ELF2FLT)
|
||||
$(INSTALL) -m 755 $(PROG_ELF2FLT) $(target_bindir)/$(PROG_ELF2FLT)
|
||||
[ -f $(bindir)/$(TARGET)-ld.real$(EXEEXT) ] || \
|
||||
mv $(bindir)/$(TARGET)-ld$(EXEEXT) $(bindir)/$(TARGET)-ld.real$(EXEEXT)
|
||||
[ -f $(target_bindir)/ld.real$(EXEEXT) ] || \
|
||||
mv $(target_bindir)/ld$(EXEEXT) $(target_bindir)/ld.real$(EXEEXT)
|
||||
$(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(bindir)/$(TARGET)-ld$(EXEEXT)
|
||||
$(INSTALL) -m 755 $(PROG_LD_ELF2FLT) $(target_bindir)/ld$(EXEEXT)
|
||||
$(INSTALL) -m 644 $(SRC_LDFILE) $(target_libdir)/$(LDFILE)
|
||||
|
||||
sinclude .deps
|
||||
.deps:
|
||||
$(CC) -MM $(CPPFLAGS) $(srcdir)/*.c > .deps
|
||||
@@ -1,62 +0,0 @@
|
||||
|
||||
README - elf2flt
|
||||
----------------
|
||||
|
||||
Copyright (C) 2001-2003, SnapGear (www.snapgear.com)
|
||||
davidm@snapgear.com
|
||||
gerg@snapgear.com
|
||||
|
||||
This is Free Software, under the GNU Public Licence v2 or greater. See
|
||||
LICENSE.TXT for more details.
|
||||
|
||||
Elf2flt with PIC, ZFLAT and full reloc support. Currently supported
|
||||
targets include: m68k/ColdFire, ARM, Sparc, NEC v850, MicroBlaze,
|
||||
h8300, SuperH, and Blackfin.
|
||||
|
||||
COMPILING:
|
||||
|
||||
You need an appropriate libbfd.a and libiberty.a for your target to
|
||||
build this tool. They are normally part of the binutils package.
|
||||
|
||||
To compile elf2flt do:
|
||||
|
||||
./configure --target=<ARCH> --with-libbfd=<libbfd.a> --with-libiberty=<libiberty.a>
|
||||
make
|
||||
make install
|
||||
|
||||
The <ARCH> argument to configure specifies what the target architecture is.
|
||||
This should be the same target as you used to build the binutils and gcc
|
||||
cross development tools. The --with-libbfd and --with-libiberty arguments
|
||||
specify where the libbfd.a and libiberty.a library files are to use.
|
||||
|
||||
|
||||
FILES:
|
||||
|
||||
README - this file
|
||||
configure - autoconf configuration shell script
|
||||
configure.in- original autoconf file
|
||||
config.* - autoconf support scripts
|
||||
Makefile.in - Makefile template used by configure
|
||||
elf2flt.c - the source
|
||||
flthdr.c - flat header manipulation program
|
||||
flat.h - header from uClinux kernel sources
|
||||
elf2flt.ld - an example linker script that works for C/C++ and uClinux
|
||||
ld-elf2flt - A linker replacement that implements a -elf2flt option for the
|
||||
linker and runs elf2flt automatically for you. It auto
|
||||
detects PIC/non-PIC code and adjusts its option accordingly.
|
||||
It uses the environment variable FLTFLAGS when running
|
||||
elf2flt. It runs /.../m68k-elf-ld.real to do the actual
|
||||
linking.
|
||||
|
||||
TIPS:
|
||||
|
||||
The ld-elf2flt produces 2 files as output. The binary flat file X, and
|
||||
X.gdb which is used for debugging and PIC purposes.
|
||||
|
||||
The '-p' option requires an elf executable linked at address 0. The
|
||||
elf2flt.ld provided will generate the correct format binary when linked
|
||||
with the real linker with *no* '-r' option for the linker.
|
||||
|
||||
The '-r' flag can be added to PIC builds to get contiguous code/data. This
|
||||
is good for loading application symbols into gdb (add-symbol-file XXX.gdb).
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Helper functions to handle compression via zlib
|
||||
*
|
||||
* Copyright (C) 2007-2008 Julian Brown
|
||||
* Copyright (C) 2008 Mike Frysinger
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <zlib.h>
|
||||
#include "compress.h"
|
||||
#include "stubs.h"
|
||||
|
||||
/* Open an (uncompressed) file as a stream. Return 0 on success, 1 on
|
||||
error.
|
||||
NOTE: The MODE argument must remain valid for the lifetime of the stream,
|
||||
because it is referred to by reopen_stream_compressed() if it is called.
|
||||
String constants work fine. */
|
||||
|
||||
int
|
||||
fopen_stream_u(stream *fp, const char *path, const char *mode)
|
||||
{
|
||||
fp->u.filep = fopen(path, mode);
|
||||
fp->type = (fp->u.filep) ? UNCOMPRESSED : INVALID;
|
||||
fp->mode = mode;
|
||||
return (fp->u.filep) ? 0 : 1;
|
||||
}
|
||||
|
||||
/* Read from stream. Return number of elements read. */
|
||||
|
||||
size_t
|
||||
fread_stream(void *ptr, size_t size, size_t nmemb, stream *str)
|
||||
{
|
||||
size_t read;
|
||||
|
||||
switch (str->type) {
|
||||
case UNCOMPRESSED:
|
||||
read = fread(ptr, size, nmemb, str->u.filep);
|
||||
break;
|
||||
|
||||
case COMPRESSED:
|
||||
read = gzread(str->u.gzfilep, ptr, size * nmemb) / size;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return read;
|
||||
}
|
||||
|
||||
/* Write to stream. Return number of elements written. */
|
||||
|
||||
size_t
|
||||
fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str)
|
||||
{
|
||||
size_t written;
|
||||
|
||||
switch (str->type) {
|
||||
case UNCOMPRESSED:
|
||||
written = fwrite(ptr, size, nmemb, str->u.filep);
|
||||
break;
|
||||
|
||||
case COMPRESSED:
|
||||
written = gzwrite(str->u.gzfilep, ptr, size * nmemb) / size;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Close stream. */
|
||||
|
||||
int
|
||||
fclose_stream(stream *str)
|
||||
{
|
||||
switch (str->type) {
|
||||
case UNCOMPRESSED:
|
||||
return fclose(str->u.filep);
|
||||
|
||||
case COMPRESSED:
|
||||
return gzclose(str->u.gzfilep);
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ferror_stream(stream *str)
|
||||
{
|
||||
switch (str->type) {
|
||||
case UNCOMPRESSED:
|
||||
return ferror(str->u.filep);
|
||||
|
||||
case COMPRESSED:
|
||||
{
|
||||
const char *err;
|
||||
int errno;
|
||||
|
||||
err = gzerror(str->u.gzfilep, &errno);
|
||||
if (errno == Z_OK || errno == Z_STREAM_END)
|
||||
return 0;
|
||||
else if (errno == Z_ERRNO)
|
||||
return 1;
|
||||
else {
|
||||
fprintf(stderr, "%s\n", err);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
fseek_stream(stream *str, long offset, int whence)
|
||||
{
|
||||
switch (str->type) {
|
||||
case UNCOMPRESSED:
|
||||
return fseek(str->u.filep, offset, whence);
|
||||
|
||||
case COMPRESSED:
|
||||
return gzseek(str->u.gzfilep, offset, whence);
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* Reopen a stream at the current file position. */
|
||||
|
||||
void
|
||||
reopen_stream_compressed(stream *str)
|
||||
{
|
||||
int fd;
|
||||
long offset, roffset;
|
||||
|
||||
/* Already a compressed stream, return immediately */
|
||||
if (str->type == COMPRESSED)
|
||||
return;
|
||||
|
||||
if (str->type == INVALID)
|
||||
abort();
|
||||
|
||||
fd = fileno(str->u.filep);
|
||||
/* Get current (buffered) file position. */
|
||||
offset = ftell(str->u.filep);
|
||||
|
||||
/* Make sure there's nothing left in buffers. */
|
||||
fflush(str->u.filep);
|
||||
|
||||
/* Reposition underlying FD. (Might be unnecessary?) */
|
||||
roffset = lseek(fd, offset, SEEK_SET);
|
||||
|
||||
assert(roffset == offset);
|
||||
|
||||
/* Reopen as compressed stream. */
|
||||
str->u.gzfilep = gzdopen(fd, str->mode);
|
||||
gzsetparams(str->u.gzfilep, 9, Z_DEFAULT_STRATEGY);
|
||||
str->type = COMPRESSED;
|
||||
}
|
||||
|
||||
void
|
||||
transfer(stream *ifp, stream *ofp, int count)
|
||||
{
|
||||
char cmd[1024];
|
||||
int n, num;
|
||||
|
||||
while (count == -1 || count > 0) {
|
||||
if (count == -1 || count > sizeof(cmd))
|
||||
num = sizeof(cmd);
|
||||
else
|
||||
num = count;
|
||||
n = fread_stream(cmd, 1, num, ifp);
|
||||
if (n == 0)
|
||||
break;
|
||||
if (fwrite_stream(cmd, n, 1, ofp) != 1)
|
||||
fatal_perror("Write failed :-(\n");
|
||||
if (count != -1)
|
||||
count -= n;
|
||||
}
|
||||
if (count > 0)
|
||||
fatal("Failed to transfer %d bytes\n", count);
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Helper functions to handle compression via zlib
|
||||
*
|
||||
* Copyright (C) 2007-2008 Julian Brown
|
||||
* Copyright (C) 2008 Mike Frysinger
|
||||
*
|
||||
* Licensed under the GPL-2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __ELF2FLT_COMPRESS_H__
|
||||
#define __ELF2FLT_COMPRESS_H__
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
INVALID,
|
||||
UNCOMPRESSED,
|
||||
COMPRESSED
|
||||
} stream_type;
|
||||
|
||||
/* Tagged union holding either a regular FILE* handle or a zlib gzFile
|
||||
handle. */
|
||||
typedef struct
|
||||
{
|
||||
stream_type type;
|
||||
const char *mode;
|
||||
union
|
||||
{
|
||||
FILE *filep;
|
||||
gzFile gzfilep;
|
||||
} u;
|
||||
} stream;
|
||||
|
||||
int fopen_stream_u(stream *fp, const char *path, const char *mode);
|
||||
size_t fread_stream(void *ptr, size_t size, size_t nmemb, stream *str);
|
||||
size_t fwrite_stream(const void *ptr, size_t size, size_t nmemb, stream *str);
|
||||
int fclose_stream(stream *str);
|
||||
int ferror_stream(stream *str);
|
||||
int fseek_stream(stream *str, long offset, int whence);
|
||||
void reopen_stream_compressed(stream *str);
|
||||
void transfer(stream *ifp, stream *ofp, int count);
|
||||
|
||||
#endif
|
||||
Vendored
-1418
File diff suppressed because it is too large
Load Diff
Vendored
-1577
File diff suppressed because it is too large
Load Diff
Vendored
-5508
File diff suppressed because it is too large
Load Diff
@@ -1,235 +0,0 @@
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
AC_INIT(elf2flt.c)
|
||||
|
||||
AC_ARG_WITH(zlib-prefix,
|
||||
AS_HELP_STRING([--with-zlib-prefix=<dir>], [path to installed zlib]),
|
||||
[ ac_zlib_prefix=$withval ],
|
||||
[ ac_zlib_prefix=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(libbfd,
|
||||
AS_HELP_STRING([--with-libbfd=<file>], [path to libbfd.a library to use]),
|
||||
[ ac_libbfd=$withval ],
|
||||
[ ac_libbfd=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(libiberty,
|
||||
AS_HELP_STRING([--with-libiberty=<file>], [path to libiberty.a library to use]),
|
||||
[ ac_libiberty=$withval ],
|
||||
[ ac_libiberty=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(bfd-include-dir,
|
||||
AS_HELP_STRING([--with-bfd-include-dir=<dir>], [include path for correct bfd.h]),
|
||||
[ ac_bfd_include_dir=$withval ],
|
||||
[ ac_bfd_include_dir=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(binutils-include-dir,
|
||||
AS_HELP_STRING([--with-binutils-include-dir=<dir>], [include path for binutils headers]),
|
||||
[ ac_binutils_include_dir=$withval ],
|
||||
[ ac_binutils_include_dir=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(binutils-ldscript-dir,
|
||||
AS_HELP_STRING([--with-binutils-ldscript-dir=<dir>], [path to install elf2flt.ld]),
|
||||
[ ac_binutils_ldscript_dir=$withval ],
|
||||
[ ac_binutils_ldscript_dir=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_WITH(binutils-build-dir,
|
||||
AS_HELP_STRING([--with-binutils-build-dir=<dir>], [path to compiled binutils tree]),
|
||||
[ ac_binutils_build_dir=$withval ],
|
||||
[ ac_binutils_build_dir=NONE ]
|
||||
)
|
||||
|
||||
AC_ARG_ENABLE(ld-elf2flt-binary,
|
||||
AS_HELP_STRING([--disable-ld-elf2flt-binary], [use ld-elf2flt shell script]),
|
||||
[ use_ld_elf2flt_binary=$enableval ],
|
||||
[ use_ld_elf2flt_binary=yes ]
|
||||
)
|
||||
|
||||
dnl convert a yes/no variable to 1/0 for C code
|
||||
var_yn_to_10() {
|
||||
if eval test \"\$$1\" = yes ; then
|
||||
eval $1=1
|
||||
else
|
||||
eval $1=0
|
||||
fi
|
||||
}
|
||||
|
||||
AC_ARG_ENABLE(got-check,
|
||||
AS_HELP_STRING([--disable-got-check], [disable check for GOT (needed on H8)]),
|
||||
[ got_check=$enableval ],
|
||||
[ got_check=yes ]
|
||||
)
|
||||
var_yn_to_10 got_check
|
||||
|
||||
AC_ARG_ENABLE(emit-relocs,
|
||||
AS_HELP_STRING([--disable-emit-relocs], [don't use the --emit-relocs (-q) linker option]),
|
||||
[ emit_relocs=$enableval ],
|
||||
[ emit_relocs=yes ]
|
||||
)
|
||||
var_yn_to_10 emit_relocs
|
||||
|
||||
AC_ARG_ENABLE(emit-ctor-dtor,
|
||||
AS_HELP_STRING([--enable-emit-ctor-dtor], [manually create ctor/dtor list]),
|
||||
[ emit_ctor_dtor=$enableval ],
|
||||
[ emit_ctor_dtor=no ]
|
||||
)
|
||||
var_yn_to_10 emit_ctor_dtor
|
||||
|
||||
AC_ARG_ENABLE(always-reloc-text,
|
||||
AS_HELP_STRING([--enable-always-reloc-text], [always process text relocs ignoring pic/got (needed on Blackfin)]),
|
||||
[ always_reloc_text=$enableval ],
|
||||
[
|
||||
case $target in
|
||||
bfin*) always_reloc_text=yes;;
|
||||
*) always_reloc_text=no;;
|
||||
esac
|
||||
]
|
||||
)
|
||||
var_yn_to_10 always_reloc_text
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
AC_PROG_INSTALL
|
||||
|
||||
if test "$ac_binutils_build_dir" != "NONE"; then
|
||||
test "$ac_libbfd" = "NONE" && ac_libbfd="$ac_binutils_build_dir/bfd/libbfd.a"
|
||||
test "$ac_libiberty" = "NONE" && ac_libiberty="$ac_binutils_build_dir/libiberty/libiberty.a"
|
||||
test "$ac_bfd_include_dir" = "NONE" && ac_bfd_include_dir="$ac_binutils_build_dir/bfd"
|
||||
test "$ac_binutils_include_dir" = "NONE" && ac_binutils_include_dir="$ac_binutils_build_dir/include"
|
||||
fi
|
||||
|
||||
dnl Checks for libraries.
|
||||
|
||||
dnl The dlopen() function is in the C library for *BSD and in
|
||||
dnl libdl on GLIBC-based systems
|
||||
AC_SEARCH_LIBS([dlopen], [dl dld], [], [
|
||||
AC_MSG_ERROR([unable to find the dlopen() function])
|
||||
])
|
||||
|
||||
if test "$ac_libiberty" = "NONE"; then
|
||||
AC_CHECK_LIB(iberty, objalloc_create)
|
||||
ac_libiberty=auto
|
||||
else
|
||||
LIBS="$ac_libiberty $LIBS"
|
||||
fi
|
||||
if test "$ac_libbfd" = "NONE"; then
|
||||
AC_CHECK_LIB(bfd, bfd_openr)
|
||||
ac_libbfd=auto
|
||||
else
|
||||
LIBS="$ac_libbfd $LIBS"
|
||||
fi
|
||||
if test "$ac_zlib_prefix" = "NONE"; then
|
||||
AC_CHECK_LIB(z, deflate)
|
||||
else
|
||||
LIBS="-L$ac_zlib_prefix/lib -lz $LIBS"
|
||||
fi
|
||||
|
||||
bfd_include_dir=
|
||||
if test "$ac_bfd_include_dir" != "NONE"; then
|
||||
bfd_include_dir="-I$ac_bfd_include_dir"
|
||||
fi
|
||||
|
||||
binutils_include_dir=
|
||||
if test "$ac_binutils_include_dir" != "NONE"; then
|
||||
binutils_include_dir="-I$ac_binutils_include_dir"
|
||||
fi
|
||||
|
||||
zlib_include_dir=
|
||||
if test "$ac_zlib_prefix" != "NONE"; then
|
||||
zlib_include_dir="-I$ac_zlib_prefix/include"
|
||||
fi
|
||||
|
||||
binutils_ldscript_dir=
|
||||
if test "$ac_binutils_ldscript_dir" = "NONE"; then
|
||||
ac_binutils_ldscript_dir="\${TOOLDIR}/../${target_alias}/lib"
|
||||
fi
|
||||
binutils_ldscript_dir="$ac_binutils_ldscript_dir"
|
||||
|
||||
if test "$ac_libbfd" = "NONE" -o "$ac_libiberty" = "NONE" ; then
|
||||
AC_MSG_ERROR([
|
||||
|
||||
You need to specify the location of the libfd.a and libiberty.a
|
||||
host libraries from the binutils package.
|
||||
|
||||
Run configure again specifying these options:
|
||||
|
||||
./configure --target=<ARCH> --with-bfd-include-dir=<dir> --with-libbfd=<libbfd.a> --with-libiberty=<libiberty.a>
|
||||
])
|
||||
fi
|
||||
|
||||
if test "$ac_bfd_include_dir" = "NONE" ; then
|
||||
AC_MSG_ERROR([
|
||||
|
||||
You need to specify the location of the bfd.h header from a
|
||||
configured/compiled version of the binutils package for your target.
|
||||
Without this your elf2flt may crash as it will try to use the
|
||||
systems bfd.h which may be from a different binutils package.
|
||||
|
||||
Run configure again specifying these options:
|
||||
|
||||
./configure --target=<ARCH> --with-bfd-include-dir=<dir> --with-libbfd=<libbfd.a> --with-libiberty=<libiberty.a>
|
||||
])
|
||||
fi
|
||||
|
||||
SYMBOL_PREFIX=
|
||||
case $target in
|
||||
h8300|bfin*)
|
||||
SYMBOL_PREFIX=_
|
||||
;;
|
||||
esac
|
||||
|
||||
dnl Make sure we resolve system symbols before libiberty/libbfd ones.
|
||||
dnl Otherwise, things like getopt get screwed up because the system headers
|
||||
dnl redirect some functions to the system symbols, but other local symbols
|
||||
dnl come from libiberty/libbfd.
|
||||
dnl int getopt(int, char * const [], const char *) __asm("_" "getopt" "$UNIX2003");
|
||||
AC_CHECK_LIB(c, malloc, LIBS="-lc $LIBS")
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(fcntl.h unistd.h bfd.h)
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
|
||||
dnl Checks for library functions.
|
||||
AC_FUNC_VPRINTF
|
||||
|
||||
AC_CHECK_FUNCS([ \
|
||||
dcgettext \
|
||||
getline \
|
||||
libintl_dgettext \
|
||||
strsignal \
|
||||
])
|
||||
|
||||
|
||||
|
||||
test "$GCC" = yes && CFLAGS="-Wall $CFLAGS"
|
||||
|
||||
dnl Subsitute values
|
||||
AC_SUBST(target)
|
||||
AC_SUBST(target_alias)
|
||||
AC_SUBST(target_cpu)
|
||||
AC_SUBST(target_os)
|
||||
AC_SUBST(target_vendor)
|
||||
AC_SUBST(bfd_include_dir)
|
||||
AC_SUBST(binutils_include_dir)
|
||||
AC_SUBST(zlib_include_dir)
|
||||
AC_SUBST(binutils_ldscript_dir)
|
||||
AC_SUBST(use_ld_elf2flt_binary)
|
||||
AC_SUBST(got_check)
|
||||
AC_SUBST(emit_relocs)
|
||||
AC_SUBST(emit_ctor_dtor)
|
||||
AC_SUBST(always_reloc_text)
|
||||
AC_SUBST(SYMBOL_PREFIX)
|
||||
|
||||
AC_OUTPUT(ld-elf2flt.sh:ld-elf2flt.in Makefile elf2flt.ld)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,161 +0,0 @@
|
||||
|
||||
ENTRY (__start)
|
||||
|
||||
MEMORY {
|
||||
flatmem : ORIGIN = 0x0, LENGTH = 0xfffffff
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
.G6 (DEFINED(G6Base) ? G6Base : 0x0) : {
|
||||
*(.G6)
|
||||
}
|
||||
.G7 (DEFINED(G7Base) ? G7Base : 0x0) : {
|
||||
*(.G7)
|
||||
}
|
||||
.G8 (DEFINED(G8Base) ? G8Base : 0x0) : {
|
||||
*(.G8)
|
||||
}
|
||||
.G9 (DEFINED(G9Base) ? G9Base : 0) : {
|
||||
*(.G9)
|
||||
}
|
||||
.G10 (DEFINED(G10Base) ? G10Base : 0) : {
|
||||
*(.G10)
|
||||
}
|
||||
.G11 (DEFINED(G11Base) ? G11Base : 0) : {
|
||||
*(.G11)
|
||||
}
|
||||
.G12 (DEFINED(G12Base) ? G12Base : 0) : {
|
||||
*(.G12)
|
||||
}
|
||||
.G13 (DEFINED(G13Base) ? G13Base : 0) : {
|
||||
*(.G13)
|
||||
}
|
||||
.text 0x0 : {
|
||||
. = . + 4;
|
||||
. = ALIGN(0x4) ;
|
||||
_stext = . ;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.warning)
|
||||
*(.stub)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.glue_7t)
|
||||
*(.glue_7)
|
||||
*(.jcr)
|
||||
*(.init)
|
||||
*(.fini)
|
||||
|
||||
W_RODAT *(.rodata)
|
||||
W_RODAT *(.rodata1)
|
||||
W_RODAT *(.rodata.*)
|
||||
|
||||
/* This is special code area at the end of the normal
|
||||
text section. It contains a small lookup table at
|
||||
the start followed by the code pointed to by entries
|
||||
in the lookup table. */
|
||||
. = ALIGN (4) ;
|
||||
PROVIDE(__ctbp = .);
|
||||
*(.call_table_data)
|
||||
*(.call_table_text)
|
||||
|
||||
. = ALIGN(0x20) ;
|
||||
_etext = . ;
|
||||
} > flatmem
|
||||
.data : {
|
||||
. = ALIGN(0x4) ;
|
||||
_sdata = . ;
|
||||
__data_start = . ;
|
||||
data_start = . ;
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
FILL(0) ;
|
||||
. = ALIGN(0x20) ;
|
||||
LONG(-1)
|
||||
. = ALIGN(0x20) ;
|
||||
R_RODAT *(.rodata)
|
||||
R_RODAT *(.rodata1)
|
||||
R_RODAT *(.rodata.*)
|
||||
*(.gnu.linkonce.r*)
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
*(.data1)
|
||||
*(.eh_frame)
|
||||
*(.gcc_except_table)
|
||||
|
||||
/* Microblaze has .sdata and .sbss (small bss). They must
|
||||
be contiguous, so please don't move any of this. JW */
|
||||
_ssrw = . ;
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.sbss) /* Don't move this! */
|
||||
_essrw = . ;
|
||||
|
||||
_ssrw_size = _essrw - _ssrw;
|
||||
PROVIDE(_SDA_BASE_ = _ssrw + (_ssrw_size / 2));
|
||||
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(__libc_atexit)
|
||||
*(__libc_subinit)
|
||||
*(__libc_subfreeres)
|
||||
*(.note.ABI-tag)
|
||||
|
||||
/* microblaze-specific read-only small data area
|
||||
and associated locating symbols */
|
||||
_ssro = . ;
|
||||
*(.sdata2)
|
||||
_essro = . ;
|
||||
_ssro_size = _essro - _ssro;
|
||||
PROVIDE(_SDA2_BASE_ = _ssro + (_ssro_size / 2));
|
||||
|
||||
. = ALIGN(4) ;
|
||||
__CTOR_LIST__ = .;
|
||||
LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2)
|
||||
*(.ctors)
|
||||
LONG(0)
|
||||
__CTOR_END__ = .;
|
||||
__DTOR_LIST__ = .;
|
||||
LONG((__DTOR_END__ - __DTOR_LIST__) / 4 - 2)
|
||||
*(.dtors)
|
||||
LONG(0)
|
||||
__DTOR_END__ = .;
|
||||
|
||||
. = ALIGN(0x10) ;
|
||||
_edata = . ;
|
||||
} > flatmem
|
||||
.bss : {
|
||||
. = ALIGN(0x4) ;
|
||||
_sbss = ALIGN(0x4) ;
|
||||
__bss_start = . ;
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.bss*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(0x10) ;
|
||||
_ebss = . ;
|
||||
_end = . ;
|
||||
end = . ;
|
||||
} > flatmem
|
||||
|
||||
.junk 0 : { *(.rel*) *(.rela*) }
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_info 0 : { *(.debug_info) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
}
|
||||
-1935
File diff suppressed because it is too large
Load Diff
@@ -1,215 +0,0 @@
|
||||
|
||||
ENTRY (@SYMBOL_PREFIX@_start)
|
||||
|
||||
MEMORY {
|
||||
flatmem : ORIGIN = 0x0, LENGTH = 0xfffffff
|
||||
}
|
||||
|
||||
PHDRS {
|
||||
text PT_LOAD ;
|
||||
data PT_LOAD ;
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
|
||||
.text 0x0 : {
|
||||
. = . + 4;
|
||||
. = ALIGN(0x4) ;
|
||||
@SYMBOL_PREFIX@_stext = . ;
|
||||
*(.text)
|
||||
*(.text.*)
|
||||
*(.gnu.warning)
|
||||
*(.stub)
|
||||
*(.gnu.linkonce.t*)
|
||||
*(.glue_7t)
|
||||
*(.glue_7)
|
||||
*(.jcr)
|
||||
. = ALIGN (4) ;
|
||||
@SYMBOL_PREFIX@__init_section = . ;
|
||||
KEEP (*(.init))
|
||||
@SYMBOL_PREFIX@__init_section_end = . ;
|
||||
@SYMBOL_PREFIX@__fini_section = . ;
|
||||
KEEP (*(.fini))
|
||||
@SYMBOL_PREFIX@__fini_section_end = . ;
|
||||
|
||||
W_RODAT *(.rodata)
|
||||
W_RODAT *(.rodata1)
|
||||
W_RODAT *(.rodata.*)
|
||||
W_RODAT *(.gnu.linkonce.r*)
|
||||
|
||||
/* This is special code area at the end of the normal
|
||||
text section. It contains a small lookup table at
|
||||
the start followed by the code pointed to by entries
|
||||
in the lookup table. */
|
||||
. = ALIGN (4) ;
|
||||
PROVIDE(@SYMBOL_PREFIX@__ctbp = .);
|
||||
*(.call_table_data)
|
||||
*(.call_table_text)
|
||||
|
||||
. = ALIGN(0x20) ;
|
||||
@SYMBOL_PREFIX@_etext = . ;
|
||||
} > flatmem :text
|
||||
|
||||
.data : {
|
||||
. = ALIGN(0x4) ;
|
||||
@SYMBOL_PREFIX@_sdata = . ;
|
||||
@SYMBOL_PREFIX@__data_start = . ;
|
||||
@SYMBOL_PREFIX@data_start = . ;
|
||||
*(.got.plt)
|
||||
*(.got)
|
||||
FILL(0) ;
|
||||
. = ALIGN(0x20) ;
|
||||
LONG(-1)
|
||||
. = ALIGN(0x20) ;
|
||||
R_RODAT *(.rodata)
|
||||
R_RODAT *(.rodata1)
|
||||
R_RODAT *(.rodata.*)
|
||||
R_RODAT *(.gnu.linkonce.r*)
|
||||
*(.data)
|
||||
*(.data1)
|
||||
*(.data.*)
|
||||
*(.gnu.linkonce.d*)
|
||||
|
||||
/* Microblaze has .sdata and .sbss (small bss). They must
|
||||
be contiguous, so please don't move any of this. JW */
|
||||
@SYMBOL_PREFIX@_ssrw = . ;
|
||||
*(.sdata)
|
||||
*(.sdata.*)
|
||||
*(.sbss) /* Don't move this! */
|
||||
*(.gnu.linkonce.sb*)
|
||||
@SYMBOL_PREFIX@_essrw = . ;
|
||||
|
||||
@SYMBOL_PREFIX@_ssrw_size = @SYMBOL_PREFIX@_essrw - @SYMBOL_PREFIX@_ssrw;
|
||||
PROVIDE(@SYMBOL_PREFIX@_SDA_BASE_ = @SYMBOL_PREFIX@_ssrw + (@SYMBOL_PREFIX@_ssrw_size / 2));
|
||||
|
||||
*(.gnu.linkonce.s.*)
|
||||
*(__libc_atexit)
|
||||
*(__libc_subinit)
|
||||
*(__libc_subfreeres)
|
||||
|
||||
/* microblaze-specific read-only small data area
|
||||
and associated locating symbols */
|
||||
@SYMBOL_PREFIX@_ssro = . ;
|
||||
*(.sdata2)
|
||||
@SYMBOL_PREFIX@_essro = . ;
|
||||
@SYMBOL_PREFIX@_ssro_size = @SYMBOL_PREFIX@_essro - @SYMBOL_PREFIX@_ssro;
|
||||
PROVIDE(@SYMBOL_PREFIX@_SDA2_BASE_ = @SYMBOL_PREFIX@_ssro + (@SYMBOL_PREFIX@_ssro_size / 2));
|
||||
|
||||
. = ALIGN(4) ;
|
||||
TOR: @SYMBOL_PREFIX@__CTOR_LIST__ = .;
|
||||
TOR: LONG((@SYMBOL_PREFIX@__CTOR_END__ - @SYMBOL_PREFIX@__CTOR_LIST__) / 4 - 2)
|
||||
SINGLE_LINK: /* gcc uses crtbegin.o to find the start of
|
||||
SINGLE_LINK: the constructors, so we make sure it is
|
||||
SINGLE_LINK: first. Because this is a wildcard, it
|
||||
SINGLE_LINK: doesn't matter if the user does not
|
||||
SINGLE_LINK: actually link against crtbegin.o; the
|
||||
SINGLE_LINK: linker won't look for a file to match a
|
||||
SINGLE_LINK: wildcard. The wildcard also means that it
|
||||
SINGLE_LINK: doesn't matter which directory crtbegin.o
|
||||
SINGLE_LINK: is in. */
|
||||
SINGLE_LINK: KEEP (*crtbegin*.o(.ctors))
|
||||
SINGLE_LINK: /* We don't want to include the .ctor section from
|
||||
SINGLE_LINK: from the crtend.o file until after the sorted ctors.
|
||||
SINGLE_LINK: The .ctor section from the crtend file contains the
|
||||
SINGLE_LINK: end of ctors marker and it must be last */
|
||||
SINGLE_LINK: KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors))
|
||||
SINGLE_LINK: KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*(.ctors))
|
||||
TOR: LONG(0)
|
||||
TOR: @SYMBOL_PREFIX@__CTOR_END__ = .;
|
||||
TOR: @SYMBOL_PREFIX@__DTOR_LIST__ = .;
|
||||
TOR: LONG((@SYMBOL_PREFIX@__DTOR_END__ - @SYMBOL_PREFIX@__DTOR_LIST__) / 4 - 2)
|
||||
SINGLE_LINK: KEEP (*crtbegin*.o(.dtors))
|
||||
SINGLE_LINK: KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors))
|
||||
SINGLE_LINK: KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*(.dtors))
|
||||
TOR: LONG(0)
|
||||
TOR: @SYMBOL_PREFIX@__DTOR_END__ = .;
|
||||
|
||||
PROVIDE (@SYMBOL_PREFIX@__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (@SYMBOL_PREFIX@__preinit_array_end = .);
|
||||
|
||||
PROVIDE (@SYMBOL_PREFIX@__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (@SYMBOL_PREFIX@__init_array_end = .);
|
||||
|
||||
PROVIDE (@SYMBOL_PREFIX@__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (@SYMBOL_PREFIX@__fini_array_end = .);
|
||||
} > flatmem :data
|
||||
|
||||
.note.ABI-tag : { *(.note.ABI-tag) } > flatmem
|
||||
.eh_frame_hdr : { *(.eh_frame_hdr) } > flatmem
|
||||
.eh_frame : { KEEP(*(.eh_frame)) } > flatmem
|
||||
.gcc_except_table : {
|
||||
KEEP(*(.gcc_except_table))
|
||||
KEEP(*(.gcc_except_table.*))
|
||||
} >flatmem
|
||||
|
||||
. = ALIGN(0x10) ;
|
||||
@SYMBOL_PREFIX@_edata = . ;
|
||||
|
||||
.bss : {
|
||||
. = ALIGN(0x4) ;
|
||||
@SYMBOL_PREFIX@_sbss = ALIGN(0x4) ;
|
||||
@SYMBOL_PREFIX@__bss_start = . ;
|
||||
*(.dynsbss)
|
||||
*(.sbss)
|
||||
*(.sbss.*)
|
||||
*(.scommon)
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(.bss.*)
|
||||
*(.bss*)
|
||||
*(.gnu.linkonce.b*)
|
||||
*(COMMON)
|
||||
. = ALIGN(0x10) ;
|
||||
@SYMBOL_PREFIX@_ebss = . ;
|
||||
@SYMBOL_PREFIX@_end = . ;
|
||||
@SYMBOL_PREFIX@end = . ;
|
||||
} > flatmem
|
||||
|
||||
.stack : {
|
||||
. = ALIGN(0x4);
|
||||
@SYMBOL_PREFIX@_stack_start = .;
|
||||
}
|
||||
|
||||
.junk 0 : { *(.rel*) *(.rela*) }
|
||||
/DISCARD/ : { *(.note.GNU-stack) }
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
/* SGI/MIPS DWARF 2 extensions */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
}
|
||||
-113
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2002-2005 David McCullough <davidm@snapgear.com>
|
||||
* Copyright (C) 1998 Kenneth Albanowski <kjahds@kjahds.com>
|
||||
* The Silver Hammer Group, Ltd.
|
||||
*
|
||||
* This file provides the definitions and structures needed to
|
||||
* support uClinux flat-format executables.
|
||||
*
|
||||
* This is Free Software, under the GNU Public Licence v2 or greater.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_FLAT_H
|
||||
#define _LINUX_FLAT_H
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include <linux/types.h>
|
||||
#include <asm/flat.h>
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#define FLAT_VERSION 0x00000004L
|
||||
|
||||
#ifdef CONFIG_BINFMT_SHARED_FLAT
|
||||
#define MAX_SHARED_LIBS (4)
|
||||
#else
|
||||
#define MAX_SHARED_LIBS (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* To make everything easier to port and manage cross platform
|
||||
* development, all fields are in network byte order.
|
||||
*/
|
||||
|
||||
struct flat_hdr {
|
||||
char magic[4];
|
||||
uint32_t rev; /* version (as above) */
|
||||
uint32_t entry; /* Offset of first executable instruction
|
||||
with text segment from beginning of file */
|
||||
uint32_t data_start; /* Offset of data segment from beginning of
|
||||
file */
|
||||
uint32_t data_end; /* Offset of end of data segment from beginning
|
||||
of file */
|
||||
uint32_t bss_end; /* Offset of end of bss segment from beginning
|
||||
of file */
|
||||
|
||||
/* (It is assumed that data_end through bss_end forms the bss segment.) */
|
||||
|
||||
uint32_t stack_size; /* Size of stack, in bytes */
|
||||
uint32_t reloc_start; /* Offset of relocation records from beginning
|
||||
of file */
|
||||
uint32_t reloc_count; /* Number of relocation records */
|
||||
uint32_t flags;
|
||||
uint32_t build_date; /* When the program/library was built */
|
||||
uint32_t filler[5]; /* Reservered, set to zero */
|
||||
};
|
||||
|
||||
#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */
|
||||
#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
|
||||
#define FLAT_FLAG_GZIP 0x0004 /* all but the header is compressed */
|
||||
#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */
|
||||
#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */
|
||||
#define FLAT_FLAG_L1STK 0x0020 /* use a 4k stack in L1 scratch memory. */
|
||||
|
||||
#ifdef __KERNEL__ /* so systems without linux headers can compile the apps */
|
||||
/*
|
||||
* While it would be nice to keep this header clean, users of older
|
||||
* tools still need this support in the kernel. So this section is
|
||||
* purely for compatibility with old tool chains.
|
||||
*
|
||||
* DO NOT make changes or enhancements to the old format please, just work
|
||||
* with the format above, except to fix bugs with old format support.
|
||||
*/
|
||||
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#define OLD_FLAT_VERSION 0x00000002L
|
||||
#define OLD_FLAT_RELOC_TYPE_TEXT 0
|
||||
#define OLD_FLAT_RELOC_TYPE_DATA 1
|
||||
#define OLD_FLAT_RELOC_TYPE_BSS 2
|
||||
|
||||
typedef union {
|
||||
uint32_t value;
|
||||
struct {
|
||||
# if defined(mc68000) && !defined(CONFIG_COLDFIRE)
|
||||
int32_t offset : 30;
|
||||
uint32_t type : 2;
|
||||
# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */
|
||||
# elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
uint32_t type : 2;
|
||||
int32_t offset : 30;
|
||||
# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */
|
||||
# elif defined(__LITTLE_ENDIAN_BITFIELD)
|
||||
int32_t offset : 30;
|
||||
uint32_t type : 2;
|
||||
# define OLD_FLAT_FLAG_RAM 0x1 /* load program entirely into RAM */
|
||||
# else
|
||||
# error "Unknown bitfield order for flat files."
|
||||
# endif
|
||||
} reloc;
|
||||
} flat_v2_reloc_t;
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_FLAT_H */
|
||||
|
||||
/* this __MUST__ be at the VERY end of the file - do NOT move!!
|
||||
* Local Variables:
|
||||
* c-basic-offset: 4
|
||||
* tab-width: 8
|
||||
* end:
|
||||
* vi: tabstop=8 shiftwidth=4 textwidth=79 noexpandtab
|
||||
*/
|
||||
@@ -1,380 +0,0 @@
|
||||
/****************************************************************************/
|
||||
/*
|
||||
* A simple program to manipulate flat files
|
||||
*
|
||||
* Copyright (C) 2001-2003 SnapGear Inc, davidm@snapgear.com
|
||||
* Copyright (C) 2001 Lineo, davidm@lineo.com
|
||||
*
|
||||
* This is Free Software, under the GNU Public Licence v2 or greater.
|
||||
*
|
||||
*/
|
||||
/****************************************************************************/
|
||||
|
||||
#include <stdio.h> /* Userland pieces of the ANSI C standard I/O package */
|
||||
#include <unistd.h> /* Userland prototypes of the Unix std system calls */
|
||||
#include <time.h>
|
||||
#include <stdlib.h> /* exit() */
|
||||
#include <string.h> /* strcat(), strcpy() */
|
||||
#include <inttypes.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "compress.h"
|
||||
#include <libiberty.h>
|
||||
|
||||
#include "stubs.h"
|
||||
const char *elf2flt_progname;
|
||||
|
||||
/* from uClinux-x.x.x/include/linux */
|
||||
#include "flat.h" /* Binary flat header description */
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#include <getopt.h>
|
||||
|
||||
#define mkstemp(p) mktemp(p)
|
||||
|
||||
#endif
|
||||
|
||||
#if defined TARGET_bfin
|
||||
# define flat_get_relocate_addr(addr) (addr & 0x03ffffff)
|
||||
#else
|
||||
# define flat_get_relocate_addr(addr) (addr)
|
||||
#endif
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
static int print = 0, print_relocs = 0, docompress = 0, ramload = 0,
|
||||
stacksize = 0, ktrace = 0, l1stack = 0;
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void
|
||||
process_file(char *ifile, char *ofile)
|
||||
{
|
||||
int old_flags, old_stack, new_flags, new_stack;
|
||||
stream ifp, ofp;
|
||||
struct flat_hdr old_hdr, new_hdr;
|
||||
char *tfile, tmpbuf[256];
|
||||
int input_error, output_error;
|
||||
|
||||
*tmpbuf = '\0';
|
||||
|
||||
if (fopen_stream_u(&ifp, ifile, "r" BINARY_FILE_OPTS)) {
|
||||
fprintf(stderr, "Cannot open %s\n", ifile);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fread_stream(&old_hdr, sizeof(old_hdr), 1, &ifp) != 1) {
|
||||
fprintf(stderr, "Cannot read header of %s\n", ifile);
|
||||
fclose_stream(&ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (strncmp(old_hdr.magic, "bFLT", 4) != 0) {
|
||||
fprintf(stderr, "Cannot read header of %s\n", ifile);
|
||||
fclose_stream(&ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
new_flags = old_flags = ntohl(old_hdr.flags);
|
||||
new_stack = old_stack = ntohl(old_hdr.stack_size);
|
||||
new_hdr = old_hdr;
|
||||
|
||||
if (docompress == 1) {
|
||||
new_flags |= FLAT_FLAG_GZIP;
|
||||
new_flags &= ~FLAT_FLAG_GZDATA;
|
||||
} else if (docompress == 2) {
|
||||
new_flags |= FLAT_FLAG_GZDATA;
|
||||
new_flags &= ~FLAT_FLAG_GZIP;
|
||||
} else if (docompress < 0)
|
||||
new_flags &= ~(FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA);
|
||||
|
||||
if (ramload > 0)
|
||||
new_flags |= FLAT_FLAG_RAM;
|
||||
else if (ramload < 0)
|
||||
new_flags &= ~FLAT_FLAG_RAM;
|
||||
|
||||
if (ktrace > 0)
|
||||
new_flags |= FLAT_FLAG_KTRACE;
|
||||
else if (ktrace < 0)
|
||||
new_flags &= ~FLAT_FLAG_KTRACE;
|
||||
|
||||
if (l1stack > 0)
|
||||
new_flags |= FLAT_FLAG_L1STK;
|
||||
else if (l1stack < 0)
|
||||
new_flags &= ~FLAT_FLAG_L1STK;
|
||||
|
||||
if (stacksize)
|
||||
new_stack = stacksize;
|
||||
|
||||
if (print == 1) {
|
||||
time_t t;
|
||||
uint32_t reloc_count, reloc_start;
|
||||
|
||||
printf("%s\n", ifile);
|
||||
printf(" Magic: %4.4s\n", old_hdr.magic);
|
||||
printf(" Rev: %d\n", ntohl(old_hdr.rev));
|
||||
t = (time_t) htonl(old_hdr.build_date);
|
||||
printf(" Build Date: %s", t?ctime(&t):"not specified\n");
|
||||
printf(" Entry: 0x%x\n", ntohl(old_hdr.entry));
|
||||
printf(" Data Start: 0x%x\n", ntohl(old_hdr.data_start));
|
||||
printf(" Data End: 0x%x\n", ntohl(old_hdr.data_end));
|
||||
printf(" BSS End: 0x%x\n", ntohl(old_hdr.bss_end));
|
||||
printf(" Stack Size: 0x%x\n", ntohl(old_hdr.stack_size));
|
||||
reloc_start = ntohl(old_hdr.reloc_start);
|
||||
printf(" Reloc Start: 0x%x\n", reloc_start);
|
||||
reloc_count = ntohl(old_hdr.reloc_count);
|
||||
printf(" Reloc Count: 0x%x\n", reloc_count);
|
||||
printf(" Flags: 0x%x ( ", ntohl(old_hdr.flags));
|
||||
if (old_flags) {
|
||||
if (old_flags & FLAT_FLAG_RAM)
|
||||
printf("Load-to-Ram ");
|
||||
if (old_flags & FLAT_FLAG_GOTPIC)
|
||||
printf("Has-PIC-GOT ");
|
||||
if (old_flags & FLAT_FLAG_GZIP)
|
||||
printf("Gzip-Compressed ");
|
||||
if (old_flags & FLAT_FLAG_GZDATA)
|
||||
printf("Gzip-Data-Compressed ");
|
||||
if (old_flags & FLAT_FLAG_KTRACE)
|
||||
printf("Kernel-Traced-Load ");
|
||||
if (old_flags & FLAT_FLAG_L1STK)
|
||||
printf("L1-Scratch-Stack ");
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
if (print_relocs) {
|
||||
uint32_t *relocs = xcalloc(reloc_count, sizeof(uint32_t));
|
||||
uint32_t i;
|
||||
unsigned long r;
|
||||
|
||||
printf(" Relocs:\n");
|
||||
printf(" #\treloc ( address )\tdata\n");
|
||||
|
||||
if (old_flags & FLAT_FLAG_GZIP)
|
||||
reopen_stream_compressed(&ifp);
|
||||
if (fseek_stream(&ifp, reloc_start, SEEK_SET)) {
|
||||
fprintf(stderr, "Cannot seek to relocs of %s\n", ifile);
|
||||
fclose_stream(&ifp);
|
||||
return;
|
||||
}
|
||||
if (fread_stream(relocs, sizeof(uint32_t), reloc_count, &ifp) == -1) {
|
||||
fprintf(stderr, "Cannot read relocs of %s\n", ifile);
|
||||
fclose_stream(&ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < reloc_count; ++i) {
|
||||
uint32_t raddr, addr;
|
||||
r = ntohl(relocs[i]);
|
||||
raddr = flat_get_relocate_addr(r);
|
||||
printf(" %u\t0x%08lx (0x%08"PRIx32")\t", i, r, raddr);
|
||||
fseek_stream(&ifp, sizeof(old_hdr) + raddr, SEEK_SET);
|
||||
fread_stream(&addr, sizeof(addr), 1, &ifp);
|
||||
printf("%"PRIx32"\n", addr);
|
||||
}
|
||||
|
||||
/* reset file position for below */
|
||||
fseek_stream(&ifp, sizeof(old_hdr), SEEK_SET);
|
||||
}
|
||||
} else if (print > 1) {
|
||||
static int first = 1;
|
||||
unsigned int text, data, bss, stk, rel, tot;
|
||||
|
||||
if (first) {
|
||||
printf("Flag Rev Text Data BSS Stack Relocs RAM Filename\n");
|
||||
printf("-----------------------------------------------------------\n");
|
||||
first = 0;
|
||||
}
|
||||
*tmpbuf = '\0';
|
||||
strcat(tmpbuf, (old_flags & FLAT_FLAG_KTRACE) ? "k" : "");
|
||||
strcat(tmpbuf, (old_flags & FLAT_FLAG_RAM) ? "r" : "");
|
||||
strcat(tmpbuf, (old_flags & FLAT_FLAG_GOTPIC) ? "p" : "");
|
||||
strcat(tmpbuf, (old_flags & FLAT_FLAG_GZIP) ? "z" :
|
||||
((old_flags & FLAT_FLAG_GZDATA) ? "d" : ""));
|
||||
printf("-%-3.3s ", tmpbuf);
|
||||
printf("%3d ", ntohl(old_hdr.rev));
|
||||
printf("%6d ", text=ntohl(old_hdr.data_start)-sizeof(struct flat_hdr));
|
||||
printf("%6d ", data=ntohl(old_hdr.data_end)-ntohl(old_hdr.data_start));
|
||||
printf("%6d ", bss=ntohl(old_hdr.bss_end)-ntohl(old_hdr.data_end));
|
||||
printf("%6d ", stk=ntohl(old_hdr.stack_size));
|
||||
printf("%6d ", rel=ntohl(old_hdr.reloc_count) * 4);
|
||||
/*
|
||||
* work out how much RAM is needed per invocation, this
|
||||
* calculation is dependent on the binfmt_flat implementation
|
||||
*/
|
||||
tot = data; /* always need data */
|
||||
|
||||
if (old_flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP))
|
||||
tot += text + sizeof(struct flat_hdr);
|
||||
|
||||
if (bss + stk > rel) /* which is bigger ? */
|
||||
tot += bss + stk;
|
||||
else
|
||||
tot += rel;
|
||||
|
||||
printf("%6d ", tot);
|
||||
/*
|
||||
* the total depends on whether the relocs are smaller/bigger than
|
||||
* the BSS
|
||||
*/
|
||||
printf("%s\n", ifile);
|
||||
}
|
||||
|
||||
/* if there is nothing else to do, leave */
|
||||
if (new_flags == old_flags && new_stack == old_stack) {
|
||||
fclose_stream(&ifp);
|
||||
return;
|
||||
}
|
||||
|
||||
new_hdr.flags = htonl(new_flags);
|
||||
new_hdr.stack_size = htonl(new_stack);
|
||||
|
||||
tfile = make_temp_file("flthdr");
|
||||
|
||||
if (fopen_stream_u(&ofp, tfile, "w" BINARY_FILE_OPTS)) {
|
||||
unlink(tfile);
|
||||
fatal("Failed to open %s for writing\n", tfile);
|
||||
}
|
||||
|
||||
/* Copy header (always uncompressed). */
|
||||
if (fwrite_stream(&new_hdr, sizeof(new_hdr), 1, &ofp) != 1) {
|
||||
unlink(tfile);
|
||||
fatal("Failed to write to %s\n", tfile);
|
||||
}
|
||||
|
||||
/* Whole input file (including text) is compressed: start decompressing
|
||||
now. */
|
||||
if (old_flags & FLAT_FLAG_GZIP)
|
||||
reopen_stream_compressed(&ifp);
|
||||
|
||||
/* Likewise, output file is compressed. Start compressing now. */
|
||||
if (new_flags & FLAT_FLAG_GZIP) {
|
||||
printf("zflat %s --> %s\n", ifile, ofile);
|
||||
reopen_stream_compressed(&ofp);
|
||||
}
|
||||
|
||||
transfer(&ifp, &ofp,
|
||||
ntohl(old_hdr.data_start) - sizeof(struct flat_hdr));
|
||||
|
||||
/* Only data and relocs were compressed in input. Start decompressing
|
||||
from here. */
|
||||
if (old_flags & FLAT_FLAG_GZDATA)
|
||||
reopen_stream_compressed(&ifp);
|
||||
|
||||
/* Only data/relocs to be compressed in output. Start compressing
|
||||
from here. */
|
||||
if (new_flags & FLAT_FLAG_GZDATA) {
|
||||
printf("zflat-data %s --> %s\n", ifile, ofile);
|
||||
reopen_stream_compressed(&ofp);
|
||||
}
|
||||
|
||||
transfer(&ifp, &ofp, -1);
|
||||
|
||||
input_error = ferror_stream(&ifp);
|
||||
output_error = ferror_stream(&ofp);
|
||||
|
||||
if (input_error || output_error) {
|
||||
unlink(tfile);
|
||||
fatal("Error on file pointer%s%s\n",
|
||||
input_error ? " input" : "",
|
||||
output_error ? " output" : "");
|
||||
}
|
||||
|
||||
fclose_stream(&ifp);
|
||||
fclose_stream(&ofp);
|
||||
|
||||
/* Copy temporary file to output location. */
|
||||
fopen_stream_u(&ifp, tfile, "r" BINARY_FILE_OPTS);
|
||||
fopen_stream_u(&ofp, ofile, "w" BINARY_FILE_OPTS);
|
||||
|
||||
transfer(&ifp, &ofp, -1);
|
||||
|
||||
fclose_stream(&ifp);
|
||||
fclose_stream(&ofp);
|
||||
|
||||
unlink(tfile);
|
||||
free(tfile);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void
|
||||
usage(char *s)
|
||||
{
|
||||
if (s)
|
||||
fprintf(stderr, "%s\n", s);
|
||||
fprintf(stderr, "usage: %s [options] flat-file\n", elf2flt_progname);
|
||||
fprintf(stderr, " Allows you to change an existing flat file\n\n");
|
||||
fprintf(stderr, " -p : print current settings\n");
|
||||
fprintf(stderr, " -P : print relocations\n");
|
||||
fprintf(stderr, " -z : compressed flat file\n");
|
||||
fprintf(stderr, " -d : compressed data-only flat file\n");
|
||||
fprintf(stderr, " -Z : un-compressed flat file\n");
|
||||
fprintf(stderr, " -r : ram load\n");
|
||||
fprintf(stderr, " -R : do not RAM load\n");
|
||||
fprintf(stderr, " -k : kernel traced load (for debug)\n");
|
||||
fprintf(stderr, " -K : normal non-kernel traced load\n");
|
||||
fprintf(stderr, " -u : place stack in L1 scratchpad memory\n");
|
||||
fprintf(stderr, " -U : place stack in normal SDRAM memory\n");
|
||||
fprintf(stderr, " -s size : stack size\n");
|
||||
fprintf(stderr, " -o file : output-file\n"
|
||||
" (default is to modify input file)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int c, noargs;
|
||||
char *ofile = NULL, *ifile;
|
||||
|
||||
elf2flt_progname = argv[0];
|
||||
|
||||
noargs = 1;
|
||||
while ((c = getopt(argc, argv, "pPdzZrRuUkKs:o:")) != EOF) {
|
||||
switch (c) {
|
||||
case 'p': print = 1; break;
|
||||
case 'P': print_relocs = 1; break;
|
||||
case 'z': docompress = 1; break;
|
||||
case 'd': docompress = 2; break;
|
||||
case 'Z': docompress = -1; break;
|
||||
case 'r': ramload = 1; break;
|
||||
case 'R': ramload = -1; break;
|
||||
case 'k': ktrace = 1; break;
|
||||
case 'K': ktrace = -1; break;
|
||||
case 'u': l1stack = 1; break;
|
||||
case 'U': l1stack = -1; break;
|
||||
case 'o': ofile = optarg; break;
|
||||
case 's':
|
||||
if (sscanf(optarg, "%i", &stacksize) != 1)
|
||||
usage("invalid stack size");
|
||||
break;
|
||||
default:
|
||||
usage("invalid option");
|
||||
break;
|
||||
}
|
||||
noargs = 0;
|
||||
}
|
||||
|
||||
if (optind >= argc)
|
||||
usage("No input files provided");
|
||||
|
||||
if (ofile && argc - optind > 1)
|
||||
usage("-o can only be used with a single file");
|
||||
|
||||
if (!print && noargs) /* no args == print */
|
||||
print = argc - optind; /* greater than 1 is short format */
|
||||
|
||||
for (c = optind; c < argc; c++) {
|
||||
ifile = argv[c];
|
||||
if (!ofile)
|
||||
ofile = ifile;
|
||||
process_file(ifile, ofile);
|
||||
ofile = NULL;
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
@@ -1,251 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# install - install a program, script, or datafile
|
||||
# This comes from X11R5 (mit/util/scripts/install.sh).
|
||||
#
|
||||
# Copyright 1991 by the Massachusetts Institute of Technology
|
||||
#
|
||||
# Permission to use, copy, modify, distribute, and sell this software and its
|
||||
# documentation for any purpose is hereby granted without fee, provided that
|
||||
# the above copyright notice appear in all copies and that both that
|
||||
# copyright notice and this permission notice appear in supporting
|
||||
# documentation, and that the name of M.I.T. not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without specific,
|
||||
# written prior permission. M.I.T. makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
# Calling this script install-sh is preferred over install.sh, to prevent
|
||||
# `make' implicit rules from creating a file called install from it
|
||||
# when there is no Makefile.
|
||||
#
|
||||
# This script is compatible with the BSD install script, but was written
|
||||
# from scratch. It can only install one file at a time, a restriction
|
||||
# shared with many OS's install programs.
|
||||
|
||||
|
||||
# set DOITPROG to echo to test this script
|
||||
|
||||
# Don't use :- since 4.3BSD and earlier shells don't like it.
|
||||
doit="${DOITPROG-}"
|
||||
|
||||
|
||||
# put in absolute paths if you don't have them in your path; or use env. vars.
|
||||
|
||||
mvprog="${MVPROG-mv}"
|
||||
cpprog="${CPPROG-cp}"
|
||||
chmodprog="${CHMODPROG-chmod}"
|
||||
chownprog="${CHOWNPROG-chown}"
|
||||
chgrpprog="${CHGRPPROG-chgrp}"
|
||||
stripprog="${STRIPPROG-strip}"
|
||||
rmprog="${RMPROG-rm}"
|
||||
mkdirprog="${MKDIRPROG-mkdir}"
|
||||
|
||||
transformbasename=""
|
||||
transform_arg=""
|
||||
instcmd="$mvprog"
|
||||
chmodcmd="$chmodprog 0755"
|
||||
chowncmd=""
|
||||
chgrpcmd=""
|
||||
stripcmd=""
|
||||
rmcmd="$rmprog -f"
|
||||
mvcmd="$mvprog"
|
||||
src=""
|
||||
dst=""
|
||||
dir_arg=""
|
||||
|
||||
while [ x"$1" != x ]; do
|
||||
case $1 in
|
||||
-c) instcmd="$cpprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-d) dir_arg=true
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-m) chmodcmd="$chmodprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-o) chowncmd="$chownprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-g) chgrpcmd="$chgrpprog $2"
|
||||
shift
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-s) stripcmd="$stripprog"
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-t=*) transformarg=`echo $1 | sed 's/-t=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
-b=*) transformbasename=`echo $1 | sed 's/-b=//'`
|
||||
shift
|
||||
continue;;
|
||||
|
||||
*) if [ x"$src" = x ]
|
||||
then
|
||||
src=$1
|
||||
else
|
||||
# this colon is to work around a 386BSD /bin/sh bug
|
||||
:
|
||||
dst=$1
|
||||
fi
|
||||
shift
|
||||
continue;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ x"$src" = x ]
|
||||
then
|
||||
echo "install: no input file specified"
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]; then
|
||||
dst=$src
|
||||
src=""
|
||||
|
||||
if [ -d $dst ]; then
|
||||
instcmd=:
|
||||
chmodcmd=""
|
||||
else
|
||||
instcmd=$mkdirprog
|
||||
fi
|
||||
else
|
||||
|
||||
# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
|
||||
# might cause directories to be created, which would be especially bad
|
||||
# if $src (and thus $dsttmp) contains '*'.
|
||||
|
||||
if [ -f $src -o -d $src ]
|
||||
then
|
||||
:
|
||||
else
|
||||
echo "install: $src does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ x"$dst" = x ]
|
||||
then
|
||||
echo "install: no destination specified"
|
||||
exit 1
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# If destination is a directory, append the input filename; if your system
|
||||
# does not like double slashes in filenames, you may need to add some logic
|
||||
|
||||
if [ -d $dst ]
|
||||
then
|
||||
dst="$dst"/`basename $src`
|
||||
else
|
||||
:
|
||||
fi
|
||||
fi
|
||||
|
||||
## this sed command emulates the dirname command
|
||||
dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
|
||||
|
||||
# Make sure that the destination directory exists.
|
||||
# this part is taken from Noah Friedman's mkinstalldirs script
|
||||
|
||||
# Skip lots of stat calls in the usual case.
|
||||
if [ ! -d "$dstdir" ]; then
|
||||
defaultIFS='
|
||||
'
|
||||
IFS="${IFS-${defaultIFS}}"
|
||||
|
||||
oIFS="${IFS}"
|
||||
# Some sh's can't handle IFS=/ for some reason.
|
||||
IFS='%'
|
||||
set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
|
||||
IFS="${oIFS}"
|
||||
|
||||
pathcomp=''
|
||||
|
||||
while [ $# -ne 0 ] ; do
|
||||
pathcomp="${pathcomp}${1}"
|
||||
shift
|
||||
|
||||
if [ ! -d "${pathcomp}" ] ;
|
||||
then
|
||||
$mkdirprog "${pathcomp}"
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
pathcomp="${pathcomp}/"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ x"$dir_arg" != x ]
|
||||
then
|
||||
$doit $instcmd $dst &&
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi
|
||||
else
|
||||
|
||||
# If we're going to rename the final executable, determine the name now.
|
||||
|
||||
if [ x"$transformarg" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
dstfile=`basename $dst $transformbasename |
|
||||
sed $transformarg`$transformbasename
|
||||
fi
|
||||
|
||||
# don't allow the sed command to completely eliminate the filename
|
||||
|
||||
if [ x"$dstfile" = x ]
|
||||
then
|
||||
dstfile=`basename $dst`
|
||||
else
|
||||
:
|
||||
fi
|
||||
|
||||
# Make a temp file name in the proper directory.
|
||||
|
||||
dsttmp=$dstdir/#inst.$$#
|
||||
|
||||
# Move or copy the file name to the temp name
|
||||
|
||||
$doit $instcmd $src $dsttmp &&
|
||||
|
||||
trap "rm -f ${dsttmp}" 0 &&
|
||||
|
||||
# and set any options; do chmod last to preserve setuid bits
|
||||
|
||||
# If any of these fail, we abort the whole thing. If we want to
|
||||
# ignore errors from any of these, just make sure not to ignore
|
||||
# errors from the above "$doit $instcmd $src $dsttmp" command.
|
||||
|
||||
if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi &&
|
||||
if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi &&
|
||||
if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi &&
|
||||
if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi &&
|
||||
|
||||
# Now rename the file to the real destination.
|
||||
|
||||
$doit $rmcmd -f $dstdir/$dstfile &&
|
||||
$doit $mvcmd $dsttmp $dstdir/$dstfile
|
||||
|
||||
fi &&
|
||||
|
||||
|
||||
exit 0
|
||||
@@ -1,580 +0,0 @@
|
||||
/*
|
||||
* Wrapper for the real linker and the elf2flt converter. This was
|
||||
* originally a simple shell script, but that doesn't work on a
|
||||
* Windows host without cygwin.
|
||||
* The proper long term solution is to add FLT as a BFD output format.
|
||||
*
|
||||
* Converted from ld-elf2flt.in by Nathan Sidwell, nathan@codesourcery.com.
|
||||
* Updated to latest elf2flt code by Mike Frysinger, vapier@gentoo.org.
|
||||
*
|
||||
* This is Free Software, under the GNU General Public License V2 or greater.
|
||||
*
|
||||
* Copyright (C) 2006, CodeSourcery Inc.
|
||||
* Copyright (C) 2009, Analog Devices, Inc.
|
||||
* Copyright (C) 2002-2003 David McCullough <davidm@snapgear.com>
|
||||
* Copyright (C) 2000, Lineo. <davidm@lineo.com>
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <libiberty.h>
|
||||
//#include <filenames.h>
|
||||
|
||||
#include "stubs.h"
|
||||
const char *elf2flt_progname;
|
||||
|
||||
static int flag_verbose = 0, flag_final = 1, have_elf2flt_options = 0,
|
||||
flag_move_data = 0, want_shared = 0;
|
||||
static const char *shared_lib_id = NULL;
|
||||
static const char *output_file = "a.out";
|
||||
static const char *linker_script = NULL;
|
||||
static const char *emulation = NULL;
|
||||
static const char *tmp_file = NULL;
|
||||
static const char *output_gdb = NULL;
|
||||
static const char *output_elf = NULL;
|
||||
static const char *output_flt = NULL;
|
||||
static options_t search_dirs, all_options, other_options, flt_options;
|
||||
|
||||
static const char *linker = NULL;
|
||||
static const char *elf2flt = NULL;
|
||||
static const char *nm = NULL;
|
||||
static const char *objdump = NULL;
|
||||
static const char *objcopy = NULL;
|
||||
static const char *ldscriptpath = BINUTILS_LDSCRIPTDIR;
|
||||
|
||||
/* A list of sed commands */
|
||||
typedef struct {
|
||||
options_t *pattern; /* '^' for start of line match, everything else verbatim */
|
||||
options_t *replacement; /* Delete line, if NULL */
|
||||
} sed_commands_t;
|
||||
|
||||
/* Initialize a sed structure */
|
||||
#define init_sed(DST) ( \
|
||||
(DST)->pattern = xmalloc(sizeof(*(DST)->pattern)), \
|
||||
(DST)->replacement = xmalloc(sizeof(*(DST)->replacement)), \
|
||||
init_options((DST)->pattern), \
|
||||
init_options((DST)->replacement) \
|
||||
)
|
||||
#define free_sed(DST) (free((DST)->pattern), free((DST)->replacement))
|
||||
|
||||
/* Append a slot for a new sed command. */
|
||||
static void append_sed(sed_commands_t *dst, const char *pattern,
|
||||
const char *replacement)
|
||||
{
|
||||
debug1("adding pattern '%s' with replacement '%s'\n",
|
||||
pattern, replacement);
|
||||
append_option(dst->pattern, pattern);
|
||||
append_option(dst->replacement, replacement);
|
||||
}
|
||||
|
||||
/* Execute an external program COMMAND. Write its stdout to OUTPUT,
|
||||
unless that is NULL. Pass the trailing NULL terminated list of
|
||||
options, followed by all those in OPTIONS, if that is non-NULL.
|
||||
Order of options is important here as we may run on systems that
|
||||
do not allow options after non-options (i.e. many BSDs). So the
|
||||
final command line will look like:
|
||||
<command> [options] [... va args ...]
|
||||
This is because [options] will (should?) never contain non-options,
|
||||
while non-options will always be passed via the [va args].
|
||||
*/
|
||||
static int
|
||||
execute(const char *command, const char *output, const options_t *options, ...)
|
||||
{
|
||||
struct pex_obj *pex;
|
||||
const char *errmsg;
|
||||
int err;
|
||||
int status;
|
||||
va_list args;
|
||||
const char *opt;
|
||||
options_t opts;
|
||||
|
||||
debug("command=%s\n", command);
|
||||
|
||||
init_options(&opts);
|
||||
append_option(&opts, command);
|
||||
if (options)
|
||||
append_options(&opts, options);
|
||||
va_start(args, options);
|
||||
while ((opt = va_arg(args, const char *)))
|
||||
append_option(&opts, opt);
|
||||
va_end(args);
|
||||
append_option(&opts, NULL);
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
||||
pex = pex_init(0, elf2flt_progname, NULL);
|
||||
if (pex == NULL)
|
||||
fatal_perror("pex_init failed");
|
||||
|
||||
if (flag_verbose) {
|
||||
unsigned ix;
|
||||
|
||||
fprintf(stderr, "Invoking:");
|
||||
for (ix = 0; ix != opts.num - 1; ix++)
|
||||
fprintf(stderr, " '%s'", opts.options[ix]);
|
||||
if (output)
|
||||
fprintf(stderr, " > '%s'", output);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
errmsg = pex_run(pex, PEX_LAST | PEX_SEARCH, command,
|
||||
(char *const *)opts.options, output, NULL, &err);
|
||||
if (errmsg != NULL) {
|
||||
if (err != 0) {
|
||||
errno = err;
|
||||
fatal_perror(errmsg);
|
||||
} else
|
||||
fatal(errmsg);
|
||||
}
|
||||
|
||||
if (!pex_get_status(pex, 1, &status))
|
||||
fatal_perror("can't get program status");
|
||||
pex_free(pex);
|
||||
|
||||
if (status) {
|
||||
if (WIFSIGNALED(status)) {
|
||||
int sig = WTERMSIG(status);
|
||||
|
||||
fatal("%s terminated with signal %d [%s]%s",
|
||||
command, sig, strsignal(sig),
|
||||
WCOREDUMP(status) ? ", core dumped" : "");
|
||||
}
|
||||
|
||||
if (WIFEXITED(status))
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/* Auto NULL terminate */
|
||||
#define execute(...) execute(__VA_ARGS__, NULL)
|
||||
|
||||
/* Apply the sed commands in SED to file NAME_IN producing file NAME_OUT */
|
||||
static void
|
||||
do_sed(const sed_commands_t *sed, const char *name_in, const char *name_out)
|
||||
{
|
||||
FILE *in, *out;
|
||||
size_t alloc = 0;
|
||||
char *line = NULL;
|
||||
ssize_t len;
|
||||
const char *pattern, *replacement;
|
||||
int ix;
|
||||
|
||||
if (flag_verbose) {
|
||||
fprintf(stderr, "emulating: sed \\\n");
|
||||
for (ix = 0; ix != sed->pattern->num; ix++) {
|
||||
pattern = sed->pattern->options[ix];
|
||||
replacement = sed->replacement->options[ix];
|
||||
if (replacement)
|
||||
fprintf(stderr, "\t-e 's/%s/%s/' \\\n", pattern, replacement);
|
||||
else
|
||||
fprintf(stderr, "\t-e '/%s/d' \\\n", pattern);
|
||||
}
|
||||
fprintf(stderr, "\t%s > %s\n", name_in, name_out);
|
||||
}
|
||||
|
||||
in = xfopen(name_in, "r");
|
||||
out = xfopen(name_out, "w");
|
||||
|
||||
while ((len = getline(&line, &alloc, in)) > 0) {
|
||||
debug2("len=%2zi line=%s", len, line);
|
||||
|
||||
for (ix = 0; ix != sed->pattern->num; ix++) {
|
||||
const char *ptr;
|
||||
int bol;
|
||||
size_t pat_len;
|
||||
|
||||
pattern = sed->pattern->options[ix];
|
||||
replacement = sed->replacement->options[ix];
|
||||
ptr = line;
|
||||
bol = pattern[0] == '^';
|
||||
|
||||
pattern += bol;
|
||||
pat_len = strlen(pattern);
|
||||
|
||||
if (!bol) {
|
||||
do {
|
||||
ptr = strchr(ptr, pattern[0]);
|
||||
if (!ptr) ;
|
||||
else if (!strncmp(ptr, pattern, pat_len))
|
||||
goto found;
|
||||
else
|
||||
ptr++;
|
||||
}
|
||||
while (ptr);
|
||||
} else if (!strncmp(ptr, pattern, pat_len)) {
|
||||
found:
|
||||
if (replacement) {
|
||||
debug2(" [modified]\n");
|
||||
fwrite(line, 1, ptr - line, out);
|
||||
fwrite(replacement, 1, strlen(replacement), out);
|
||||
fwrite(ptr + pat_len, 1,
|
||||
len - pat_len - (ptr - line),
|
||||
out);
|
||||
} else
|
||||
debug2(" {dropped}\n");
|
||||
goto next_line;
|
||||
}
|
||||
}
|
||||
|
||||
debug2("(untouched)\n");
|
||||
fwrite(line, 1, len, out);
|
||||
next_line:
|
||||
;
|
||||
}
|
||||
fclose(in);
|
||||
if (fclose(out))
|
||||
fatal_perror("error writing temporary script '%s'", name_out);
|
||||
free(line);
|
||||
}
|
||||
|
||||
/* Generate the flt binary along with any other necessary pieces. */
|
||||
#define exec_or_ret(...) \
|
||||
do { \
|
||||
int status = execute(__VA_ARGS__); \
|
||||
if (status) return status; \
|
||||
} while (0)
|
||||
static int do_final_link(void)
|
||||
{
|
||||
sed_commands_t sed;
|
||||
struct stat buf;
|
||||
const char *script;
|
||||
const char *rel_output;
|
||||
int have_got = 0;
|
||||
FILE *in;
|
||||
char *line = NULL;
|
||||
size_t alloc = 0;
|
||||
ssize_t len;
|
||||
|
||||
init_sed(&sed);
|
||||
|
||||
if (flag_move_data) {
|
||||
FILE *in;
|
||||
|
||||
/* See if the .rodata section contains any relocations. */
|
||||
if (!output_flt)
|
||||
output_flt = make_temp_file(NULL);
|
||||
exec_or_ret(linker, NULL, &other_options, "-r", "-d", "-o", output_flt);
|
||||
exec_or_ret(objdump, tmp_file, NULL, "-h", output_flt);
|
||||
|
||||
in = xfopen(tmp_file, "r");
|
||||
while ((len = getline(&line, &alloc, in)) > 0) {
|
||||
const char *ptr = line;
|
||||
|
||||
while (1) {
|
||||
ptr = strchr(ptr, '.');
|
||||
if (!ptr)
|
||||
break;
|
||||
if (streqn(ptr, ".rodata")) {
|
||||
getline(&line, &alloc, in);
|
||||
ptr = line;
|
||||
while (1) {
|
||||
ptr = strchr(ptr, 'R');
|
||||
if (!ptr)
|
||||
break;
|
||||
if (streqn(ptr, "RELOC")) {
|
||||
flag_move_data = 0;
|
||||
fprintf(stderr, "warning: .rodata section contains relocations");
|
||||
break;
|
||||
} else
|
||||
ptr++;
|
||||
}
|
||||
break;
|
||||
} else
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
}
|
||||
append_sed(&sed, "^R_RODAT", flag_move_data ? NULL : "");
|
||||
append_sed(&sed, "^W_RODAT", flag_move_data ? "" : NULL);
|
||||
append_sed(&sed, "^SINGLE_LINK:", USE_EMIT_RELOCS ? "" : NULL);
|
||||
append_sed(&sed, "^TOR:", EMIT_CTOR_DTOR ? "" : NULL);
|
||||
|
||||
if (shared_lib_id) {
|
||||
const char *got_offset;
|
||||
int adj, id = strtol(shared_lib_id, NULL, 0);
|
||||
char buf[30];
|
||||
|
||||
/* Replace addresses using the shared object id. */
|
||||
sprintf(buf, "%.2X", id);
|
||||
append_sed(&sed, "ORIGIN = 0x0,", concat("ORIGIN = 0x", buf, "000000,", NULL));
|
||||
append_sed(&sed, ".text 0x0 :", concat(".text 0x0", buf, "000000 :", NULL));
|
||||
if (id)
|
||||
append_sed(&sed, "ENTRY (" SYMBOL_PREFIX "_start)", "ENTRY (lib_main)");
|
||||
|
||||
/* Provide the symbol specifying the library's data segment
|
||||
pointer offset. */
|
||||
adj = 4;
|
||||
if (streq(TARGET_CPU, "h8300"))
|
||||
got_offset = "__current_shared_library_er5_offset_";
|
||||
else if (streq(TARGET_CPU, "bfin"))
|
||||
got_offset = "_current_shared_library_p5_offset_", adj = 1;
|
||||
else
|
||||
got_offset = "_current_shared_library_a5_offset_";
|
||||
append_option(&other_options, "-defsym");
|
||||
sprintf(buf, "%d", id * -adj - adj);
|
||||
append_option(&other_options, concat(got_offset, "=", buf, NULL));
|
||||
}
|
||||
|
||||
/* Locate the default linker script, if we don't have one provided. */
|
||||
if (!linker_script)
|
||||
linker_script = concat(ldscriptpath, "/elf2flt.ld", NULL);
|
||||
|
||||
/* Try and locate the linker script. */
|
||||
script = linker_script;
|
||||
if (stat(script, &buf) || !S_ISREG(buf.st_mode)) {
|
||||
script = concat(ldscriptpath, "/", linker_script, NULL);
|
||||
if (stat(script, &buf) || !S_ISREG(buf.st_mode)) {
|
||||
script = concat(ldscriptpath, "/ldscripts/", linker_script, NULL);
|
||||
if (stat(script, &buf) || !S_ISREG(buf.st_mode))
|
||||
script = NULL;
|
||||
}
|
||||
}
|
||||
/* And process it if we can -- if we can't find it, the user must
|
||||
know what they are doing. */
|
||||
if (script) {
|
||||
do_sed(&sed, linker_script, tmp_file);
|
||||
linker_script = tmp_file;
|
||||
}
|
||||
free_sed(&sed);
|
||||
|
||||
if (USE_EMIT_RELOCS) {
|
||||
|
||||
exec_or_ret(linker, NULL, &other_options,
|
||||
"-T", linker_script, "-q", "-o", output_gdb, emulation);
|
||||
|
||||
append_option(&flt_options, "-a");
|
||||
rel_output = output_gdb;
|
||||
|
||||
} else if (NO_GOT_CHECK) {
|
||||
|
||||
output_elf = make_temp_file(NULL);
|
||||
|
||||
exec_or_ret(linker, NULL, &other_options,
|
||||
"-T", linker_script, "-Ur", "-d", "-o", output_elf, emulation);
|
||||
exec_or_ret(linker, NULL, &other_options,
|
||||
"-T", linker_script, "-o", output_gdb, emulation);
|
||||
|
||||
rel_output = output_elf;
|
||||
|
||||
} else {
|
||||
|
||||
output_flt = make_temp_file(NULL);
|
||||
exec_or_ret(linker, NULL, &other_options,
|
||||
"-r", "-d", "-o", output_flt, emulation);
|
||||
|
||||
output_elf = make_temp_file(NULL);
|
||||
exec_or_ret(linker, NULL, &search_dirs,
|
||||
"-T", linker_script, "-Ur", "-o", output_elf, output_flt, emulation);
|
||||
|
||||
exec_or_ret(linker, NULL, &search_dirs,
|
||||
"-T", linker_script, "-o", output_gdb, output_flt, emulation);
|
||||
|
||||
rel_output = output_elf;
|
||||
|
||||
}
|
||||
|
||||
if (shared_lib_id && strtol(shared_lib_id, NULL, 0) != 0)
|
||||
exec_or_ret(objcopy, NULL, NULL, "--localize-hidden", "--weaken", output_gdb);
|
||||
|
||||
exec_or_ret(nm, tmp_file, NULL, "-p", output_gdb);
|
||||
in = xfopen(tmp_file, "r");
|
||||
while ((len = getline(&line, &alloc, in)) > 0) {
|
||||
const char *ptr = strchr(line, '_');
|
||||
if (ptr && streqn(ptr, "_GLOBAL_OFFSET_TABLE")) {
|
||||
have_got = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose(in);
|
||||
if (have_got)
|
||||
exec_or_ret(elf2flt, NULL, &flt_options,
|
||||
"-o", output_file, "-p", output_gdb, rel_output);
|
||||
else
|
||||
exec_or_ret(elf2flt, NULL, &flt_options,
|
||||
"-o", output_file, "-r", rel_output);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* parse all the arguments provided to us */
|
||||
static void parse_args(int argc, char **argv)
|
||||
{
|
||||
char *fltflags;
|
||||
int argno;
|
||||
|
||||
for (argno = 1; argno < argc; argno++) {
|
||||
char const *arg = argv[argno];
|
||||
int to_all = argno;
|
||||
|
||||
if (streq(arg, "-elf2flt")) {
|
||||
have_elf2flt_options = 1;
|
||||
to_all++;
|
||||
} else if (streqn(arg, "-elf2flt=")) {
|
||||
have_elf2flt_options = 1;
|
||||
append_option_str(&flt_options, &arg[9], "\t ");
|
||||
to_all++;
|
||||
} else if (streq(arg, "-move-rodata")) {
|
||||
flag_move_data = 1;
|
||||
} else if (streq(arg, "-shared-lib-id")) {
|
||||
shared_lib_id = argv[++argno];
|
||||
} else if (streq(arg, "-shared") || streq(arg, "-G")) {
|
||||
want_shared = 1;
|
||||
} else if (streqn(arg, "-o")) {
|
||||
output_file = arg[2] ? &arg[2] : argv[++argno];
|
||||
} else if (streqn(arg, "-T")) {
|
||||
linker_script = arg[2] ? &arg[2] : argv[++argno];
|
||||
} else if (streq(arg, "-c")) {
|
||||
linker_script = argv[++argno];
|
||||
} else if (streqn(arg, "-L")) {
|
||||
const char *merged =
|
||||
(arg[2] ? arg : concat("-L", argv[++argno], NULL));
|
||||
append_option(&other_options, merged);
|
||||
append_option(&search_dirs, merged);
|
||||
} else if (streq(arg, "-EB")) {
|
||||
append_option(&other_options, arg);
|
||||
append_option(&search_dirs, arg);
|
||||
} else if (streq(arg, "-relax")) {
|
||||
;
|
||||
} else if (streq(arg, "-s") || streq(arg, "--strip-all") ||
|
||||
streq(arg, "-S") || streq(arg, "--strip-debug")) {
|
||||
/* Ignore these strip options for links involving elf2flt.
|
||||
The final flat output will be stripped by definition, and we
|
||||
don't want to strip the .gdb helper file. The strip options
|
||||
are also incompatible with -r and --emit-relocs. */
|
||||
;
|
||||
} else if (streq(arg, "-r") || streq(arg, "-Ur")) {
|
||||
flag_final = 0;
|
||||
append_option(&other_options, arg);
|
||||
} else if (streq(arg, "--verbose")) {
|
||||
flag_verbose = 1;
|
||||
append_option(&other_options, arg);
|
||||
} else if (streqn(arg, "-m")) {
|
||||
emulation = arg[2] ? arg : concat("-m", argv[++argno], NULL);
|
||||
} else
|
||||
append_option(&other_options, arg);
|
||||
|
||||
while (to_all <= argno)
|
||||
append_option(&all_options, argv[to_all++]);
|
||||
}
|
||||
|
||||
fltflags = getenv("FLTFLAGS");
|
||||
if (fltflags)
|
||||
append_option_str(&flt_options, fltflags, "\t ");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *argv0 = argv[0];
|
||||
const char *argv0_dir = make_relative_prefix(argv0, "/", "/");
|
||||
char *tooldir = argv0_dir;
|
||||
char *bindir = argv0_dir;
|
||||
char *tmp;
|
||||
struct stat buf;
|
||||
const char *have_exe = NULL;
|
||||
int status;
|
||||
|
||||
#ifdef __WIN32
|
||||
/* Remove the .exe extension, if it's there. */
|
||||
size_t len = strlen(argv0);
|
||||
if (len > 4 && streq(&argv0[len - 4], ".exe")) {
|
||||
have_exe = ".exe";
|
||||
len -= 4;
|
||||
argv0 = tmp = xstrdup(argv0);
|
||||
tmp[len] = 0;
|
||||
argv[0][len] = '\0';
|
||||
}
|
||||
#endif
|
||||
elf2flt_progname = lbasename(argv0);
|
||||
|
||||
/* The standard binutils tool layout has:
|
||||
|
||||
bin/<TARGET_ALIAS>-foo
|
||||
lib/
|
||||
<TARGET_ALIAS>/bin/foo
|
||||
<TARGET_ALIAS>/lib
|
||||
|
||||
It's <TARGET_ALIAS>/ that we want here: files in lib/ are for
|
||||
the host while those in <TARGET_ALIAS>/lib are for the target.
|
||||
Make bindir point to the bin dir for bin/<TARGET_ALIAS>-foo.
|
||||
Make tooldir point to the bin dir for <TARGET_ALIAS>/bin/foo. */
|
||||
if (streqn(elf2flt_progname, TARGET_ALIAS)) {
|
||||
tmp = concat(argv0_dir, "../" TARGET_ALIAS "/bin", NULL);
|
||||
if (stat(tmp, &buf) == 0 && S_ISDIR(buf.st_mode)) {
|
||||
tooldir = concat(tmp, "/", NULL);
|
||||
}
|
||||
} else {
|
||||
tmp = concat(argv0_dir, "../../bin", NULL);
|
||||
if (stat(tmp, &buf) == 0 && S_ISDIR(buf.st_mode)) {
|
||||
bindir = concat(tmp, "/", NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Typically ld-elf2flt is invoked as `ld` which means error
|
||||
* messages from it will look like "ld: " which is completely
|
||||
* confusing. So append an identifier to keep things clear.
|
||||
*/
|
||||
elf2flt_progname = concat(elf2flt_progname, " (ld-elf2flt)", NULL);
|
||||
|
||||
xmalloc_set_program_name(elf2flt_progname);
|
||||
|
||||
linker = concat(tooldir, "ld.real", have_exe, NULL);
|
||||
elf2flt = concat(tooldir, "elf2flt", have_exe, NULL);
|
||||
nm = concat(tooldir, "nm", have_exe, NULL);
|
||||
objdump = concat(bindir, TARGET_ALIAS "-objdump", have_exe, NULL);
|
||||
objcopy = concat(bindir, TARGET_ALIAS "-objcopy", have_exe, NULL);
|
||||
|
||||
if (stat(ldscriptpath, &buf) || !S_ISDIR(buf.st_mode))
|
||||
ldscriptpath = concat(tooldir, "../lib", NULL);
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
||||
if (flag_verbose) {
|
||||
fprintf(stderr, "argv[0] = '%s'\n", argv[0]);
|
||||
fprintf(stderr, "bindir = '%s'\n", bindir);
|
||||
fprintf(stderr, "tooldir = '%s'\n", tooldir);
|
||||
fprintf(stderr, "linker = '%s'\n", linker);
|
||||
fprintf(stderr, "elf2flt = '%s'\n", elf2flt);
|
||||
fprintf(stderr, "nm = '%s'\n", nm);
|
||||
fprintf(stderr, "objdump = '%s'\n", objdump);
|
||||
fprintf(stderr, "objcopy = '%s'\n", objcopy);
|
||||
fprintf(stderr, "ldscriptpath = '%s'\n", ldscriptpath);
|
||||
}
|
||||
|
||||
/* Pass off to regular linker, if there's nothing elf2flt-like */
|
||||
if (!have_elf2flt_options)
|
||||
return execute(linker, NULL, &all_options);
|
||||
|
||||
/* Pass off to regular linker, minus the elf2flt options, if it's
|
||||
not the final link. */
|
||||
if (!flag_final)
|
||||
return execute(linker, NULL, &other_options, "-o", output_file);
|
||||
|
||||
if (want_shared && !shared_lib_id)
|
||||
fatal("-shared used without passing a shared library ID");
|
||||
|
||||
/* Otherwise link & convert to flt. */
|
||||
output_gdb = concat(output_file, ".gdb", NULL);
|
||||
tmp_file = make_temp_file(NULL);
|
||||
status = do_final_link();
|
||||
if (!flag_verbose) {
|
||||
unlink(tmp_file);
|
||||
unlink(output_flt);
|
||||
unlink(output_elf);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"leaving elf2flt temp files behind:\n"
|
||||
"tmp_file = %s\n"
|
||||
"output_flt = %s\n"
|
||||
"output_elf = %s\n",
|
||||
tmp_file, output_flt, output_elf);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
@@ -1,241 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# allow us to do flat processing if the flag -Wl,-elf2flt or -elf2flt to
|
||||
# the 'C' compiler or linker respectively
|
||||
#
|
||||
# uses the env. var FLTFLAGS as extra parameters to pass to elf2flt
|
||||
# arguments given like -Wl,-elf2flt="-b 10000 -v" are given before FLTFLAGS
|
||||
#
|
||||
# Copyright (C) 2002,2003 David McCullough <davidm@snapgear.com>
|
||||
# Copyright (C) 2000, Lineo. davidm@lineo.com
|
||||
#
|
||||
# This is Free Software, under the GNU Public Licence v2 or greater.
|
||||
#
|
||||
|
||||
LINKER="$0.real" # the original renamed-linker
|
||||
ELF2FLT="`expr $0 : '\(.*\)ld'`elf2flt"
|
||||
NM="`expr $0 : '\(.*\)ld'`nm"
|
||||
TOOLDIR="`dirname $0`" # let gcc find the tools for us
|
||||
OBJCOPY="`expr $0 : '\(.*\)ld'`objcopy"
|
||||
[ -f "$OBJCOPY" ] || OBJCOPY="$TOOLDIR/../../bin/@target_alias@-objcopy"
|
||||
OBJDUMP="`expr $OBJCOPY : '\(.*\)objcopy'`objdump"
|
||||
LDSCRIPTPATH="@binutils_ldscript_dir@" # and the scripts
|
||||
SHARED_ID=""
|
||||
NEWLDSCRIPT=""
|
||||
WANT_SHARED=""
|
||||
|
||||
# check TOOLDIR from prefix/bin/ or prefix/target-alias/bin/
|
||||
[ -d "${LDSCRIPTPATH}" ] || LDSCRIPTPATH="${TOOLDIR}/../lib"
|
||||
|
||||
#
|
||||
# if we have the elf2flt options, run it
|
||||
#
|
||||
|
||||
if expr "$*" : ".*-elf2flt.*" > /dev/null
|
||||
then
|
||||
ARG1=
|
||||
ARG2=
|
||||
OFILE="a.out"
|
||||
PIC=
|
||||
SDIRS=
|
||||
LDSCRIPT=
|
||||
FINAL="yes"
|
||||
FINAL_ONLY=
|
||||
MOVDAT=
|
||||
VERBOSE=
|
||||
|
||||
while [ $# -ne 0 ]
|
||||
do
|
||||
case "$1" in
|
||||
|
||||
-elf2flt) ;; # we already know this
|
||||
-elf2flt*)FLTFLAGS="`expr \"$1\" : '-elf2flt=\(.*\)'` $FLTFLAGS";;
|
||||
|
||||
-move-rodata)
|
||||
MOVDAT="y";; # Put rodata in ROM if possible
|
||||
-s|-S|--strip-all|--strip-debug)
|
||||
;; # Ignore strip flags
|
||||
|
||||
-shared-lib-id)
|
||||
shift; SHARED_ID="$1";; # Shared library ID
|
||||
-shared|-G)
|
||||
WANT_SHARED="y";; # Shared library
|
||||
|
||||
-o) shift; OFILE="$1";; # the final outfile
|
||||
-o*) OFILE="`expr \"$1\" : '-o\(.*\)'`";;
|
||||
|
||||
-T) shift; LDSCRIPT="$1";; # they have a linker script
|
||||
-c) shift; LDSCRIPT="$1";;
|
||||
|
||||
-L) ARG1="$ARG1 $1" # remember search dirs
|
||||
shift;
|
||||
ARG1="$ARG1 $1"
|
||||
SDIRS="$SDIRS -L$1"
|
||||
;;
|
||||
-L*) ARG1="$ARG1 $1"; SDIRS="$SDIRS $1";;
|
||||
|
||||
-EB) ARG1="$ARG1 $1"; SDIRS="$SDIRS $1";; # arm big endian
|
||||
|
||||
-relax) ;; # eat this for microblaze
|
||||
|
||||
-r|-Ur) FINAL="" # this is not a final link
|
||||
ARG1="$ARG1 $1"
|
||||
;;
|
||||
|
||||
-v|--verbose)
|
||||
ARG1="$ARG1 $1"
|
||||
VERBOSE="y"
|
||||
;;
|
||||
|
||||
-m) shift; EMUL="-m $1";; # ld emulations for h8300
|
||||
-m*) EMUL=$1;;
|
||||
|
||||
*) ARG1="$ARG1 $1"
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
if [ "$WANT_SHARED" = "y" ]
|
||||
then
|
||||
if [ -z "$SHARED_ID" ]
|
||||
then
|
||||
echo "-shared used without passing a shared library ID"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
if [ "$FINAL" = "yes" ]
|
||||
then
|
||||
[ "$VERBOSE" = "y" ] && set -x
|
||||
ARG1="$ARG1 $FINAL_ONLY"
|
||||
NEWLDSCRIPT=`mktemp /tmp/flt-XXXXXX`
|
||||
trap 'rm -f "$NEWLDSCRIPT"' EXIT
|
||||
SEDOP=" -e s/^R_RODAT// -e /^W_RODAT/d"
|
||||
OBJCOPYOP=""
|
||||
if [ "$MOVDAT" ]
|
||||
then
|
||||
$LINKER -r -d -o "$OFILE.elf2flt" $ARG1 || exit $?
|
||||
if [ "`$OBJDUMP -h "$OFILE.elf2flt" | \
|
||||
egrep -A1 '[.]rodata' | grep RELOC`" ]
|
||||
then
|
||||
echo "warning: .rodata section contains relocations"
|
||||
else
|
||||
SEDOP="-e /^R_RODAT/d -e s/^W_RODAT//"
|
||||
fi
|
||||
fi
|
||||
if [ "$SHARED_ID" ]
|
||||
then
|
||||
# Massage the linker script into something useful. These
|
||||
# regexps are ugly due to some bizzare shell quoting rules.
|
||||
# SEDOP="$SEDOP -e \"s/ORIGIN = 0x0,/ORIGIN = 0x${SHARED_ID}000000,/\""
|
||||
# SEDOP="$SEDOP -e \"s/.text 0x0 :/.text 0x${SHARED_ID}000000 :/\""
|
||||
SEDOP="$SEDOP -e s/\\(ORIGIN.=.0\\)x0,/\\1x${SHARED_ID}000000,/"
|
||||
SEDOP="$SEDOP -e s/\\([.]text.0\\)x0[^0-9]:/\\1x${SHARED_ID}000000:/"
|
||||
|
||||
if [ "$SHARED_ID" -gt 0 ]
|
||||
then
|
||||
# Non application modules enter via main not _start
|
||||
# SEDOP="$SEDOP -e 's/ENTRY (_start)/ENTRY (main)/'"
|
||||
SEDOP="$SEDOP -e s/\\(ENTRY.\\)(@SYMBOL_PREFIX@_start)/\1(lib_main)/"
|
||||
OBJCOPYOP="--localize-hidden --weaken"
|
||||
fi
|
||||
|
||||
# Provide the magic parameter that defines the library data segment pointer offset
|
||||
GOT_ADJ=4
|
||||
case "@target_cpu@" in
|
||||
bfin) GOT_OFFSET="_current_shared_library_p5_offset_" GOT_ADJ=1;;
|
||||
h8300) GOT_OFFSET="__current_shared_library_er5_offset_";;
|
||||
*) GOT_OFFSET="_current_shared_library_a5_offset_";;
|
||||
esac
|
||||
ARG1="$ARG1 -defsym $GOT_OFFSET=`expr ${SHARED_ID} '*' -${GOT_ADJ} - ${GOT_ADJ}`"
|
||||
fi
|
||||
if [ "@emit_relocs@" = "1" ]
|
||||
then
|
||||
SEDOP="$SEDOP -e s/^SINGLE_LINK://"
|
||||
else
|
||||
SEDOP="$SEDOP -e /^SINGLE_LINK:/d"
|
||||
fi
|
||||
if [ "@emit_ctor_dtor@" = "1" ]
|
||||
then
|
||||
SEDOP="$SEDOP -e s/^TOR://"
|
||||
else
|
||||
SEDOP="$SEDOP -e /^TOR:/d"
|
||||
fi
|
||||
|
||||
# provide a default linker script, we usually need one
|
||||
[ -z "$LDSCRIPT" ] && LDSCRIPT="${LDSCRIPTPATH}/elf2flt.ld"
|
||||
|
||||
# if we can find the linker script we preprocess it, otherwise
|
||||
# we assume the user knows what they are doing
|
||||
if [ -f "$LDSCRIPT" ]; then
|
||||
sed $SEDOP < "$LDSCRIPT" > "$NEWLDSCRIPT"
|
||||
LDSCRIPT="$NEWLDSCRIPT"
|
||||
elif [ -f "${LDSCRIPTPATH}/$LDSCRIPT" ]; then
|
||||
sed $SEDOP < "${LDSCRIPTPATH}/$LDSCRIPT" > "$NEWLDSCRIPT"
|
||||
LDSCRIPT="$NEWLDSCRIPT"
|
||||
elif [ -f "${LDSCRIPTPATH}/ldscripts/$LDSCRIPT" ]; then
|
||||
sed $SEDOP < "${LDSCRIPTPATH}/ldscripts/$LDSCRIPT" > "$NEWLDSCRIPT"
|
||||
LDSCRIPT="$NEWLDSCRIPT"
|
||||
fi
|
||||
|
||||
if [ "@emit_relocs@" = "1" ]
|
||||
then
|
||||
$LINKER $EMUL $SDIRS -T $LDSCRIPT -q -o "$OFILE.gdb" $ARG1 ||exit $?
|
||||
RFILE="$OFILE.gdb"
|
||||
FLTFLAGS="$FLTFLAGS -a"
|
||||
else
|
||||
if [ "@got_check@" = "0" ]
|
||||
then
|
||||
$LINKER $EMUL $SDIRS -T $LDSCRIPT -Ur -d -o "$OFILE.elf" $ARG1 ||exit $?
|
||||
$LINKER $EMUL $SDIRS -T $LDSCRIPT -o "$OFILE.gdb" $ARG1 ||exit $?
|
||||
else
|
||||
$LINKER $EMUL -r -d -o "$OFILE.elf2flt" $ARG1 ||exit $?
|
||||
$LINKER $EMUL $SDIRS -T $LDSCRIPT -Ur -o "$OFILE.elf" "$OFILE.elf2flt" ||exit $?
|
||||
$LINKER $EMUL $SDIRS -T $LDSCRIPT -o "$OFILE.gdb" "$OFILE.elf2flt" ||exit $?
|
||||
rm -f "$OFILE.elf2flt"
|
||||
fi
|
||||
RFILE="$OFILE.elf"
|
||||
fi
|
||||
if $NM "$OFILE.gdb" | grep _GLOBAL_OFFSET_TABLE_ > /dev/null
|
||||
then
|
||||
$ELF2FLT $FLTFLAGS -o "$OFILE" -p "$OFILE.gdb" "$RFILE" || exit $?
|
||||
else
|
||||
$ELF2FLT $FLTFLAGS -o "$OFILE" -r "$RFILE" || exit $?
|
||||
fi
|
||||
if [ "$OBJCOPYOP" ]
|
||||
then
|
||||
if $OBJCOPY $OBJCOPYOP --help > /dev/null 2>&1
|
||||
then
|
||||
$OBJCOPY $OBJCOPYOP "$OFILE.gdb" ||exit $?
|
||||
else
|
||||
case " $OBJCOPYOP " in
|
||||
*" --localize-hidden "*)
|
||||
SYMS=`mktemp /tmp/flt-XXXXXX`
|
||||
$OBJDUMP --syms "$OFILE.gdb" > "$SYMS" ||exit $?
|
||||
sed -n 's/.*\(\.hidden\|\.internal\) \(.*\)/-L \2/p' < "$SYMS" > "$SYMS.hidden" ||exit $?
|
||||
if [ -s "$SYMS.hidden" ]
|
||||
then
|
||||
xargs ${VERBOSE:+-t} $OBJCOPY "$OFILE.gdb" < "$SYMS.hidden" ||exit $?
|
||||
fi
|
||||
rm -f "$SYMS" "$SYMS.hidden"
|
||||
;;
|
||||
esac
|
||||
case " $OBJCOPYOP " in
|
||||
*" --weaken "*)
|
||||
$OBJCOPY --weaken "$OFILE.gdb" ||exit $?
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
[ "$RFILE" = "$OFILE.gdb" ] || rm -f "$RFILE" # not needed for any reason
|
||||
exit 0
|
||||
fi
|
||||
|
||||
exec $LINKER -o "$OFILE" $ARG1
|
||||
fi
|
||||
|
||||
#
|
||||
# otherwise pretend we aren't here
|
||||
#
|
||||
|
||||
exec $LINKER "$@"
|
||||
-133
@@ -1,133 +0,0 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libiberty.h"
|
||||
|
||||
#include "stubs.h"
|
||||
|
||||
#ifndef HAVE_DCGETTEXT
|
||||
const char *dcgettext(const char *domain, const char *msg, int category)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
#endif /* !HAVE_DCGETTEXT */
|
||||
|
||||
#ifndef HAVE_LIBINTL_DGETTEXT
|
||||
const char *libintl_dgettext(const char *domain, const char *msg)
|
||||
{
|
||||
return msg;
|
||||
}
|
||||
#endif /* !HAVE_LIBINTL_DGETTEXT */
|
||||
|
||||
#ifndef HAVE_GETLINE
|
||||
/* Read a line from IN. LINE points to a malloc'd buffer that is extended as
|
||||
necessary. ALLOC points to the allocated length of LINE. Returns
|
||||
the length of the string read (including any trailing \n) */
|
||||
|
||||
ssize_t getline(char **line, size_t *alloc, FILE *in)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
if (!*alloc) {
|
||||
*alloc = 200;
|
||||
*line = xmalloc(*alloc);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (!fgets(*line + len, *alloc - len, in))
|
||||
return 0;
|
||||
len += strlen(*line + len);
|
||||
if (len && (*line)[len - 1] == '\n')
|
||||
return len;
|
||||
|
||||
*alloc *= 2;
|
||||
*line = xrealloc(*line, *alloc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fatal error & exit */
|
||||
void fatal(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
fprintf(stderr, "%s: ", elf2flt_progname);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, "\n");
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* fatal error, perror & exit */
|
||||
void fatal_perror(const char *format, ...)
|
||||
{
|
||||
int e = errno;
|
||||
va_list args;
|
||||
|
||||
va_start(args, format);
|
||||
fprintf(stderr, "%s: ", elf2flt_progname);
|
||||
vfprintf(stderr, format, args);
|
||||
fprintf(stderr, ": %s\n", strerror(e));
|
||||
va_end(args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* open a file or fail */
|
||||
FILE *xfopen(const char *path, const char *mode)
|
||||
{
|
||||
FILE *ret = fopen(path, mode);
|
||||
if (!ret)
|
||||
fatal_perror("Unable to open '%s'", path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Append a string SRC to an options array DST */
|
||||
void append_option(options_t *dst, const char *src)
|
||||
{
|
||||
if (dst->alloc == dst->num) {
|
||||
size_t a = (dst->num + 2) * 2;
|
||||
void *o = xmalloc(sizeof(*dst->options) * a);
|
||||
|
||||
memcpy(o, dst->options, sizeof(*dst->options) * dst->num);
|
||||
free(dst->options);
|
||||
dst->options = o;
|
||||
dst->alloc = a;
|
||||
}
|
||||
|
||||
dst->options[dst->num] = src;
|
||||
dst->num++;
|
||||
}
|
||||
|
||||
/* Split and append a string SRC to an options array DST */
|
||||
void append_option_str(options_t *dst, const char *src, const char *delim)
|
||||
{
|
||||
char *tok_src = xstrdup(src);
|
||||
char *tok = strtok(tok_src, delim);
|
||||
while (tok) {
|
||||
append_option(dst, tok);
|
||||
tok = strtok(NULL, delim);
|
||||
}
|
||||
/* don't free tok_src since options_t now points to it */
|
||||
}
|
||||
|
||||
/* Append an options array SRC to another options array DST */
|
||||
void append_options(options_t *dst, const options_t *src)
|
||||
{
|
||||
if (dst->alloc < dst->num + src->num) {
|
||||
size_t a = (dst->num + src->num + 2) * 2;
|
||||
void *o = xmalloc(sizeof(*dst->options) * a);
|
||||
|
||||
memcpy(o, dst->options, sizeof(*dst->options) * dst->num);
|
||||
free(dst->options);
|
||||
dst->options = o;
|
||||
dst->alloc = a;
|
||||
}
|
||||
|
||||
memcpy(&dst->options[dst->num], &src->options[0],
|
||||
sizeof(*dst->options) * src->num);
|
||||
dst->num += src->num;
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* macros for conversion between host and (internet) network byte order */
|
||||
#ifndef WIN32
|
||||
# include <netinet/in.h> /* Consts and structs defined by the internet system */
|
||||
# define BINARY_FILE_OPTS
|
||||
#else
|
||||
# include <winsock2.h>
|
||||
# define BINARY_FILE_OPTS "b"
|
||||
#endif
|
||||
|
||||
#ifndef __WIN32
|
||||
# include <sys/wait.h>
|
||||
#endif
|
||||
#ifndef WIFSIGNALED
|
||||
# define WIFSIGNALED(S) (((S) & 0xff) != 0 && ((S) & 0xff) != 0x7f)
|
||||
#endif
|
||||
#ifndef WTERMSIG
|
||||
# define WTERMSIG(S) ((S) & 0x7f)
|
||||
#endif
|
||||
#ifndef WIFEXITED
|
||||
# define WIFEXITED(S) (((S) & 0xff) == 0)
|
||||
#endif
|
||||
#ifndef WEXITSTATUS
|
||||
# define WEXITSTATUS(S) (((S) & 0xff00) >> 8)
|
||||
#endif
|
||||
#ifndef WCOREDUMP
|
||||
# define WCOREDUMP(S) ((S) & WCOREFLG)
|
||||
#endif
|
||||
#ifndef WCOREFLG
|
||||
# define WCOREFLG 0200
|
||||
#endif
|
||||
#ifndef HAVE_STRSIGNAL
|
||||
# define strsignal(sig) "SIG???"
|
||||
#endif
|
||||
|
||||
#define streq(str1, str2) (strcmp(str1, str2) == 0)
|
||||
#define streqn(str1, str2) (strncmp(str1, str2, strlen(str2)) == 0)
|
||||
|
||||
#ifndef DEBUG
|
||||
# define DEBUG -1
|
||||
#endif
|
||||
#define _debug(lvl, fmt, args...) \
|
||||
do { \
|
||||
if (lvl <= DEBUG) { \
|
||||
fprintf(stderr, "%s:%i: " fmt, __func__, __LINE__ , ## args); \
|
||||
fflush(stderr); \
|
||||
} \
|
||||
} while (0)
|
||||
#define debug2(...) _debug(2, __VA_ARGS__)
|
||||
#define debug1(...) _debug(1, __VA_ARGS__)
|
||||
#define debug0(...) _debug(0, __VA_ARGS__)
|
||||
#define debug(...) debug0(__VA_ARGS__)
|
||||
|
||||
#ifndef HAVE_GETLINE
|
||||
ssize_t getline(char **line, size_t *alloc, FILE *in);
|
||||
#endif
|
||||
|
||||
extern const char *elf2flt_progname;
|
||||
|
||||
void fatal(const char *, ...);
|
||||
void fatal_perror(const char *, ...);
|
||||
|
||||
FILE *xfopen(const char *path, const char *mode);
|
||||
|
||||
/* Structure to hold a list of options */
|
||||
typedef struct
|
||||
{
|
||||
const char **options;
|
||||
size_t num;
|
||||
size_t alloc;
|
||||
} options_t;
|
||||
/* Initialize an options structure */
|
||||
#define init_options(DST) ((DST)->options = NULL, (DST)->num = (DST)->alloc = 0)
|
||||
void append_options(options_t *dst, const options_t *src);
|
||||
void append_option(options_t *dst, const char *src);
|
||||
void append_option_str(options_t *dst, const char *src, const char *delim);
|
||||
@@ -1934,6 +1934,15 @@ m68k-*-elf* | fido-*-elf*)
|
||||
esac
|
||||
;;
|
||||
m68k-*-macos* | fido-*-elf*)
|
||||
default_m68k_cpu=68020
|
||||
default_cf_cpu=5206
|
||||
tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68k-macos.h"
|
||||
tm_defines="${tm_defines} MOTOROLA=1"
|
||||
tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf"
|
||||
tmake_file="$tmake_file m68k/t-mlibs"
|
||||
;;
|
||||
|
||||
fido-*-elf*)
|
||||
default_m68k_cpu=68020
|
||||
default_cf_cpu=5206
|
||||
tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
#define LIBGCC_SPEC "-lretrocrt -lgcc"
|
||||
#define LINK_SPEC "-elf2mac -q -undefined=_consolewrite"
|
||||
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC ""
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC ""
|
||||
|
||||
@@ -6724,7 +6724,8 @@ m68k_write_macsbug_name(FILE *file, const char *name)
|
||||
int len = strlen(name);
|
||||
if(len > 255)
|
||||
len = 255;
|
||||
|
||||
if(flag_function_sections)
|
||||
fprintf(file, "\t.section .text.%s.macsbug,\"ax\",@progbits\n",name);
|
||||
fprintf(file, "# macsbug symbol\n");
|
||||
if(!retro68_hack_asm_rts_counter)
|
||||
fprintf(file, "\trts\n");
|
||||
@@ -6735,6 +6736,8 @@ m68k_write_macsbug_name(FILE *file, const char *name)
|
||||
|
||||
ASM_OUTPUT_ASCII(file, name, len);
|
||||
fprintf(file, "\t.align 2,0\n\t.short 0\n");
|
||||
if(flag_function_sections)
|
||||
fprintf(file, "\t.section .text.%s,\"ax\",@progbits\n",name);
|
||||
}
|
||||
|
||||
static tree
|
||||
|
||||
@@ -54,8 +54,6 @@ along with GCC; see the file COPYING3. If not see
|
||||
|
||||
#define SUBTARGET_EXTRA_SPECS
|
||||
|
||||
#define LIBGCC_SPEC "-lretrocrt -lgcc"
|
||||
#define LINK_SPEC "-elf2flt -q -undefined=_consolewrite"
|
||||
|
||||
/* Note that some other tm.h files include this one and then override
|
||||
many of the definitions that relate to assembler syntax. */
|
||||
@@ -996,9 +994,9 @@ extern int m68k_sched_indexed_address_bypass_p (rtx_insn *, rtx_insn *);
|
||||
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
|
||||
do \
|
||||
{ \
|
||||
m68k_write_macsbug_name(FILE, FNAME); \
|
||||
if (!flag_inhibit_size_directive) \
|
||||
ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
|
||||
m68k_write_macsbug_name(FILE, FNAME); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
|
||||
@@ -233,6 +233,7 @@ LIBGCC2_DEBUG_CFLAGS = -g
|
||||
LIBGCC2_CFLAGS = -O2 $(LIBGCC2_INCLUDES) $(GCC_CFLAGS) $(HOST_LIBGCC2_CFLAGS) \
|
||||
$(LIBGCC2_DEBUG_CFLAGS) -DIN_LIBGCC2 \
|
||||
-fbuilding-libgcc -fno-stack-protector \
|
||||
-ffunction-sections \
|
||||
$(INHIBIT_LIBC_CFLAGS)
|
||||
|
||||
# Additional options to use when compiling libgcc2.a.
|
||||
|
||||
@@ -654,6 +654,10 @@ case "${host}" in
|
||||
newlib_cflags="${newlib_cflags} -DHAVE_RENAME -DHAVE_SYSTEM -DMISSING_SYSCALL_NAMES -DMALLOC_PROVIDED"
|
||||
syscall_dir=
|
||||
;;
|
||||
m68k-apple-macos)
|
||||
newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES -DMALLOC_PROVIDED"
|
||||
newlib_cflags="${newlib_cflags} -ffunction-sections"
|
||||
;;
|
||||
mcore-*-*)
|
||||
syscall_dir=syscalls
|
||||
;;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
file(GLOB ELF_FILES src/*.c src/*.h include/*.h)
|
||||
add_library(ELF ${ELF_FILES}
|
||||
)
|
||||
target_include_directories(ELF PRIVATE src)
|
||||
target_include_directories(ELF PUBLIC include)
|
||||
target_link_libraries(ELF -lz)
|
||||
target_compile_definitions(ELF PRIVATE HAVE_CONFIG_H)
|
||||
+674
@@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. 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
|
||||
them 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 prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. 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.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
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
|
||||
state 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) <year> <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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program 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, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU 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 Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ 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
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,8 +55,8 @@ 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
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
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
|
||||
@@ -168,7 +168,7 @@ 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
|
||||
@@ -225,7 +225,7 @@ 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
|
||||
@@ -255,7 +255,7 @@ 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
|
||||
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
|
||||
@@ -277,9 +277,9 @@ 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
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
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
|
||||
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
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.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
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
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser 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
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
+1493
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,95 @@
|
||||
Fundamental design decision:
|
||||
|
||||
- the sizes of external and internal types are assumed to be the same.
|
||||
This leaves byte ordering aside. While assuming this the code can be
|
||||
greatly simplified and speed increases. Since no change violating this
|
||||
assumption is in sight this is believed to be a worthwhile optimization.
|
||||
|
||||
- the ABI of the backend modules is not guaranteed. Really, no guarantee
|
||||
whatsoever. We are enforcing this in the code. The modules and their
|
||||
users must match. No third-party EBL module are supported or allowed.
|
||||
The only reason there are separate modules is to not have the code for
|
||||
all architectures in all the binaries.
|
||||
|
||||
- although the public libraries (libasm, libdw) have a stable API and are
|
||||
backwards ABI compatible they, and the elfutils tools, do depend on each
|
||||
others internals, and on internals of libelf to provide their interfaces.
|
||||
So they should always be upgraded in lockstep when packaging the tools
|
||||
and libraries separately. For one example of how to do that, see the
|
||||
config/elfutils.spec.
|
||||
|
||||
Some notes:
|
||||
|
||||
- old GNU ld's behavior wrt DSOs seems to be severely broken.
|
||||
|
||||
y.o reference foo()
|
||||
y1.o defines foo(), references bar()
|
||||
y2.o defines bar()
|
||||
libbar.so defines bar()
|
||||
|
||||
Running
|
||||
|
||||
gcc -o y y.o -lbar y1.o y2.o
|
||||
|
||||
uses the bar() definition from libbar.so and does not mention the definition
|
||||
in y2.o at all (no duplicate symbol message). Correct is to use the
|
||||
definition in y2.o.
|
||||
|
||||
|
||||
y.o reference foo()
|
||||
y1.o defines foo(), references bar()
|
||||
y2.o in liby2.a defines bar()
|
||||
libbar.so defines bar()
|
||||
|
||||
Running
|
||||
|
||||
gcc -o y y.o -lbar y1.o -ly3
|
||||
|
||||
has to use the definition in -lbar and not pull the definition from liby3.a.
|
||||
|
||||
|
||||
- the old linker follows DT_NEEDED entries and adds the objects referenced
|
||||
this way which define a symbol which is needed as a DT_NEEDED to the
|
||||
generated binary. This is wrong since the DT_NEEDED changes the search
|
||||
path in the object (which is breadth first).
|
||||
|
||||
|
||||
- the old linker supported extern "C++", extern "java" in version scripts.
|
||||
I believe this implementation is severly broken and needs a redesign
|
||||
(how do wildcards work with these languages*?). Therefore it is left
|
||||
out for now.
|
||||
|
||||
|
||||
- what should happen if two sections in different files with the same
|
||||
name have different types and/or the flags are different
|
||||
|
||||
|
||||
- section names in input files are mostly irrelevant. Exceptions:
|
||||
|
||||
.comment/SHT_PROGBITS in strip, ld
|
||||
|
||||
.debug \
|
||||
.line |
|
||||
.debug_srcinfo |
|
||||
.debug_sfnames |
|
||||
.debug_aranges |
|
||||
.debug_pubnames |
|
||||
.debug_info |
|
||||
.debug_abbrev |
|
||||
.debug_line |
|
||||
.debug_abbrev > DWARF sections in ld
|
||||
.debug_line |
|
||||
.debug_frame |
|
||||
.debug_str |
|
||||
.debug_loc |
|
||||
.debug_macinfo |
|
||||
.debug_weaknames |
|
||||
.debug_funcnames |
|
||||
.debug_typenames |
|
||||
.debug_varnames /
|
||||
|
||||
Sections created in output files follow the naming of special section
|
||||
from the gABI.
|
||||
|
||||
In no place is a section solely indentified by its name. Internal
|
||||
references always use the section index.
|
||||
@@ -0,0 +1,24 @@
|
||||
This directory contains a subset of elfutils, ripped out from the rest for use in Retro68.
|
||||
|
||||
The elfutils project provides libraries and tools for ELF files and DWARF data.
|
||||
|
||||
The project home is http://elfutils.org/
|
||||
|
||||
Releases are published at ftp://sourceware.org/pub/elfutils/
|
||||
Which can also be found at https://sourceware.org/elfutils/ftp/
|
||||
|
||||
Please reports bugs at https://sourceware.org/bugzilla/
|
||||
|
||||
The current elfutils source code can be checked out with
|
||||
git clone git://sourceware.org/git/elfutils.git
|
||||
|
||||
The developer mailinglist to send patches to is
|
||||
elfutils-devel@sourceware.org.
|
||||
https://sourceware.org/ml/elfutils-devel/
|
||||
|
||||
To subscribe send an email to elfutils-devel-subscribe@sourceware.org
|
||||
Or use the form at https://sourceware.org/lists.html#ml-requestor
|
||||
|
||||
See the CONTRIBUTING file for how to propose patches to the code.
|
||||
|
||||
See the NOTES files for some design decisions and notes.
|
||||
@@ -0,0 +1,6 @@
|
||||
At least the following have submitted valuable patches:
|
||||
|
||||
Jeff Johnson building. rpm wrestling
|
||||
Alexander Larsson separate debug info
|
||||
Jakub Jelinek bug fixes, testing
|
||||
Denys Vlasenko bug fuxes
|
||||
+1283
-246
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,342 @@
|
||||
/* This file defines generic ELF types, structures, and macros.
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GELF_H
|
||||
#define _GELF_H 1
|
||||
|
||||
#include <libelf.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Class independent type definitions. Correctly speaking this is not
|
||||
true. We assume that 64-bit binaries are the largest class and
|
||||
therefore all other classes can be represented without loss. */
|
||||
|
||||
/* Type for a 16-bit quantity. */
|
||||
typedef Elf64_Half GElf_Half;
|
||||
|
||||
/* Types for signed and unsigned 32-bit quantities. */
|
||||
typedef Elf64_Word GElf_Word;
|
||||
typedef Elf64_Sword GElf_Sword;
|
||||
|
||||
/* Types for signed and unsigned 64-bit quantities. */
|
||||
typedef Elf64_Xword GElf_Xword;
|
||||
typedef Elf64_Sxword GElf_Sxword;
|
||||
|
||||
/* Type of addresses. */
|
||||
typedef Elf64_Addr GElf_Addr;
|
||||
|
||||
/* Type of file offsets. */
|
||||
typedef Elf64_Off GElf_Off;
|
||||
|
||||
|
||||
/* The ELF file header. This appears at the start of every ELF file. */
|
||||
typedef Elf64_Ehdr GElf_Ehdr;
|
||||
|
||||
/* Section header. */
|
||||
typedef Elf64_Shdr GElf_Shdr;
|
||||
|
||||
/* Section index. */
|
||||
/* XXX This should probably be a larger type in preparation of times when
|
||||
regular section indices can be larger. */
|
||||
typedef Elf64_Section GElf_Section;
|
||||
|
||||
/* Symbol table entry. */
|
||||
typedef Elf64_Sym GElf_Sym;
|
||||
|
||||
/* The syminfo section if available contains additional information about
|
||||
every dynamic symbol. */
|
||||
typedef Elf64_Syminfo GElf_Syminfo;
|
||||
|
||||
/* Relocation table entry without addend (in section of type SHT_REL). */
|
||||
typedef Elf64_Rel GElf_Rel;
|
||||
|
||||
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||||
typedef Elf64_Rela GElf_Rela;
|
||||
|
||||
/* Program segment header. */
|
||||
typedef Elf64_Phdr GElf_Phdr;
|
||||
|
||||
/* Header of a compressed section. */
|
||||
typedef Elf64_Chdr GElf_Chdr;
|
||||
|
||||
/* Dynamic section entry. */
|
||||
typedef Elf64_Dyn GElf_Dyn;
|
||||
|
||||
|
||||
/* Version definition sections. */
|
||||
typedef Elf64_Verdef GElf_Verdef;
|
||||
|
||||
/* Auxialiary version information. */
|
||||
typedef Elf64_Verdaux GElf_Verdaux;
|
||||
|
||||
/* Version dependency section. */
|
||||
typedef Elf64_Verneed GElf_Verneed;
|
||||
|
||||
/* Auxiliary needed version information. */
|
||||
typedef Elf64_Vernaux GElf_Vernaux;
|
||||
|
||||
|
||||
/* Type for version symbol information. */
|
||||
typedef Elf64_Versym GElf_Versym;
|
||||
|
||||
|
||||
/* Auxiliary vector. */
|
||||
typedef Elf64_auxv_t GElf_auxv_t;
|
||||
|
||||
|
||||
/* Note section contents. */
|
||||
typedef Elf64_Nhdr GElf_Nhdr;
|
||||
|
||||
|
||||
/* Move structure. */
|
||||
typedef Elf64_Move GElf_Move;
|
||||
|
||||
|
||||
/* Library list structure. */
|
||||
typedef Elf64_Lib GElf_Lib;
|
||||
|
||||
|
||||
/* How to extract and insert information held in the st_info field. */
|
||||
|
||||
#define GELF_ST_BIND(val) ELF64_ST_BIND (val)
|
||||
#define GELF_ST_TYPE(val) ELF64_ST_TYPE (val)
|
||||
#define GELF_ST_INFO(bind, type) ELF64_ST_INFO (bind, type)
|
||||
|
||||
/* How to extract information held in the st_other field. */
|
||||
|
||||
#define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val)
|
||||
|
||||
|
||||
/* How to extract and insert information held in the r_info field. */
|
||||
|
||||
#define GELF_R_SYM(info) ELF64_R_SYM (info)
|
||||
#define GELF_R_TYPE(info) ELF64_R_TYPE (info)
|
||||
#define GELF_R_INFO(sym, type) ELF64_R_INFO (sym, type)
|
||||
|
||||
|
||||
/* How to extract and insert information held in the m_info field. */
|
||||
#define GELF_M_SYM(info) ELF64_M_SYM (info)
|
||||
#define GELF_M_SIZE(info) ELF64_M_SIZE (info)
|
||||
#define GELF_M_INFO(sym, size) ELF64_M_INFO (sym, size)
|
||||
|
||||
|
||||
/* Get class of the file associated with ELF. */
|
||||
extern int gelf_getclass (Elf *__elf);
|
||||
|
||||
|
||||
/* Return size of array of COUNT elements of the type denoted by TYPE
|
||||
in the external representation. The binary class is taken from ELF.
|
||||
The result is based on version VERSION of the ELF standard. */
|
||||
extern size_t gelf_fsize (Elf *__elf, Elf_Type __type, size_t __count,
|
||||
unsigned int __version);
|
||||
|
||||
/* Retrieve object file header. */
|
||||
extern GElf_Ehdr *gelf_getehdr (Elf *__elf, GElf_Ehdr *__dest);
|
||||
|
||||
/* Update the ELF header. */
|
||||
extern int gelf_update_ehdr (Elf *__elf, GElf_Ehdr *__src);
|
||||
|
||||
/* Create new ELF header if none exists. Creates an Elf32_Ehdr if CLASS
|
||||
is ELFCLASS32 or an Elf64_Ehdr if CLASS is ELFCLASS64. Returns NULL
|
||||
on error. */
|
||||
extern void *gelf_newehdr (Elf *__elf, int __class);
|
||||
|
||||
/* Get section at OFFSET. */
|
||||
extern Elf_Scn *gelf_offscn (Elf *__elf, GElf_Off __offset);
|
||||
|
||||
/* Retrieve section header. */
|
||||
extern GElf_Shdr *gelf_getshdr (Elf_Scn *__scn, GElf_Shdr *__dst);
|
||||
|
||||
/* Update section header. */
|
||||
extern int gelf_update_shdr (Elf_Scn *__scn, GElf_Shdr *__src);
|
||||
|
||||
/* Retrieve program header table entry. */
|
||||
extern GElf_Phdr *gelf_getphdr (Elf *__elf, int __ndx, GElf_Phdr *__dst);
|
||||
|
||||
/* Update the program header. */
|
||||
extern int gelf_update_phdr (Elf *__elf, int __ndx, GElf_Phdr *__src);
|
||||
|
||||
/* Create new program header with PHNUM entries. Creates either an
|
||||
Elf32_Phdr or an Elf64_Phdr depending on whether the given ELF is
|
||||
ELFCLASS32 or ELFCLASS64. Returns NULL on error. */
|
||||
extern void *gelf_newphdr (Elf *__elf, size_t __phnum);
|
||||
|
||||
/* Get compression header of section if any. Returns NULL and sets
|
||||
elf_errno if the section isn't compressed or an error occurred. */
|
||||
extern GElf_Chdr *gelf_getchdr (Elf_Scn *__scn, GElf_Chdr *__dst);
|
||||
|
||||
/* Convert data structure from the representation in the file represented
|
||||
by ELF to their memory representation. */
|
||||
extern Elf_Data *gelf_xlatetom (Elf *__elf, Elf_Data *__dest,
|
||||
const Elf_Data *__src, unsigned int __encode);
|
||||
|
||||
/* Convert data structure from to the representation in memory
|
||||
represented by ELF file representation. */
|
||||
extern Elf_Data *gelf_xlatetof (Elf *__elf, Elf_Data *__dest,
|
||||
const Elf_Data *__src, unsigned int __encode);
|
||||
|
||||
|
||||
/* Retrieve REL relocation info at the given index. */
|
||||
extern GElf_Rel *gelf_getrel (Elf_Data *__data, int __ndx, GElf_Rel *__dst);
|
||||
|
||||
/* Retrieve RELA relocation info at the given index. */
|
||||
extern GElf_Rela *gelf_getrela (Elf_Data *__data, int __ndx, GElf_Rela *__dst);
|
||||
|
||||
/* Update REL relocation information at given index. */
|
||||
extern int gelf_update_rel (Elf_Data *__dst, int __ndx, GElf_Rel *__src);
|
||||
|
||||
/* Update RELA relocation information at given index. */
|
||||
extern int gelf_update_rela (Elf_Data *__dst, int __ndx, GElf_Rela *__src);
|
||||
|
||||
|
||||
/* Retrieve symbol information from the symbol table at the given index. */
|
||||
extern GElf_Sym *gelf_getsym (Elf_Data *__data, int __ndx, GElf_Sym *__dst);
|
||||
|
||||
/* Update symbol information in the symbol table at the given index. */
|
||||
extern int gelf_update_sym (Elf_Data *__data, int __ndx, GElf_Sym *__src);
|
||||
|
||||
|
||||
/* Retrieve symbol information and separate section index from the
|
||||
symbol table at the given index. */
|
||||
extern GElf_Sym *gelf_getsymshndx (Elf_Data *__symdata, Elf_Data *__shndxdata,
|
||||
int __ndx, GElf_Sym *__sym,
|
||||
Elf32_Word *__xshndx);
|
||||
|
||||
/* Update symbol information and separate section index in the symbol
|
||||
table at the given index. */
|
||||
extern int gelf_update_symshndx (Elf_Data *__symdata, Elf_Data *__shndxdata,
|
||||
int __ndx, GElf_Sym *__sym,
|
||||
Elf32_Word __xshndx);
|
||||
|
||||
|
||||
/* Retrieve additional symbol information from the symbol table at the
|
||||
given index. */
|
||||
extern GElf_Syminfo *gelf_getsyminfo (Elf_Data *__data, int __ndx,
|
||||
GElf_Syminfo *__dst);
|
||||
|
||||
/* Update additional symbol information in the symbol table at the
|
||||
given index. */
|
||||
extern int gelf_update_syminfo (Elf_Data *__data, int __ndx,
|
||||
GElf_Syminfo *__src);
|
||||
|
||||
|
||||
/* Get information from dynamic table at the given index. */
|
||||
extern GElf_Dyn *gelf_getdyn (Elf_Data *__data, int __ndx, GElf_Dyn *__dst);
|
||||
|
||||
/* Update information in dynamic table at the given index. */
|
||||
extern int gelf_update_dyn (Elf_Data *__dst, int __ndx, GElf_Dyn *__src);
|
||||
|
||||
|
||||
/* Get move structure at the given index. */
|
||||
extern GElf_Move *gelf_getmove (Elf_Data *__data, int __ndx, GElf_Move *__dst);
|
||||
|
||||
/* Update move structure at the given index. */
|
||||
extern int gelf_update_move (Elf_Data *__data, int __ndx,
|
||||
GElf_Move *__src);
|
||||
|
||||
|
||||
/* Get library from table at the given index. */
|
||||
extern GElf_Lib *gelf_getlib (Elf_Data *__data, int __ndx, GElf_Lib *__dst);
|
||||
|
||||
/* Update library in table at the given index. */
|
||||
extern int gelf_update_lib (Elf_Data *__data, int __ndx, GElf_Lib *__src);
|
||||
|
||||
|
||||
|
||||
/* Retrieve symbol version information at given index. */
|
||||
extern GElf_Versym *gelf_getversym (Elf_Data *__data, int __ndx,
|
||||
GElf_Versym *__dst);
|
||||
|
||||
/* Update symbol version information. */
|
||||
extern int gelf_update_versym (Elf_Data *__data, int __ndx,
|
||||
GElf_Versym *__src);
|
||||
|
||||
|
||||
/* Retrieve required symbol version information at given offset. */
|
||||
extern GElf_Verneed *gelf_getverneed (Elf_Data *__data, int __offset,
|
||||
GElf_Verneed *__dst);
|
||||
|
||||
/* Update required symbol version information. */
|
||||
extern int gelf_update_verneed (Elf_Data *__data, int __offset,
|
||||
GElf_Verneed *__src);
|
||||
|
||||
/* Retrieve additional required symbol version information at given offset. */
|
||||
extern GElf_Vernaux *gelf_getvernaux (Elf_Data *__data, int __offset,
|
||||
GElf_Vernaux *__dst);
|
||||
|
||||
/* Update additional required symbol version information. */
|
||||
extern int gelf_update_vernaux (Elf_Data *__data, int __offset,
|
||||
GElf_Vernaux *__src);
|
||||
|
||||
|
||||
/* Retrieve symbol version definition information at given offset. */
|
||||
extern GElf_Verdef *gelf_getverdef (Elf_Data *__data, int __offset,
|
||||
GElf_Verdef *__dst);
|
||||
|
||||
/* Update symbol version definition information. */
|
||||
extern int gelf_update_verdef (Elf_Data *__data, int __offset,
|
||||
GElf_Verdef *__src);
|
||||
|
||||
/* Retrieve additional symbol version definition information at given
|
||||
offset. */
|
||||
extern GElf_Verdaux *gelf_getverdaux (Elf_Data *__data, int __offset,
|
||||
GElf_Verdaux *__dst);
|
||||
|
||||
/* Update additional symbol version definition information. */
|
||||
extern int gelf_update_verdaux (Elf_Data *__data, int __offset,
|
||||
GElf_Verdaux *__src);
|
||||
|
||||
|
||||
/* Get auxv entry at the given index. */
|
||||
extern GElf_auxv_t *gelf_getauxv (Elf_Data *__data, int __ndx,
|
||||
GElf_auxv_t *__dst);
|
||||
|
||||
/* Update auxv entry at the given index. */
|
||||
extern int gelf_update_auxv (Elf_Data *__data, int __ndx, GElf_auxv_t *__src);
|
||||
|
||||
|
||||
/* Get note header at the given offset into the data, and the offsets of
|
||||
the note's name and descriptor data. Returns the offset of the next
|
||||
note header, or 0 for an invalid offset or corrupt note header. */
|
||||
extern size_t gelf_getnote (Elf_Data *__data, size_t __offset,
|
||||
GElf_Nhdr *__result,
|
||||
size_t *__name_offset, size_t *__desc_offset);
|
||||
|
||||
|
||||
/* Compute simple checksum from permanent parts of the ELF file. */
|
||||
extern long int gelf_checksum (Elf *__elf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* gelf.h */
|
||||
@@ -0,0 +1,515 @@
|
||||
/* Interface for libelf.
|
||||
Copyright (C) 1998-2010, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _LIBELF_H
|
||||
#define _LIBELF_H 1
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/* Get the ELF types. */
|
||||
#include <elf.h>
|
||||
|
||||
#ifndef SHF_COMPRESSED
|
||||
/* Older glibc elf.h might not yet define the ELF compression types. */
|
||||
#define SHF_COMPRESSED (1 << 11) /* Section with compressed data. */
|
||||
|
||||
/* Section compression header. Used when SHF_COMPRESSED is set. */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf32_Word ch_type; /* Compression format. */
|
||||
Elf32_Word ch_size; /* Uncompressed data size. */
|
||||
Elf32_Word ch_addralign; /* Uncompressed data alignment. */
|
||||
} Elf32_Chdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Elf64_Word ch_type; /* Compression format. */
|
||||
Elf64_Word ch_reserved;
|
||||
Elf64_Xword ch_size; /* Uncompressed data size. */
|
||||
Elf64_Xword ch_addralign; /* Uncompressed data alignment. */
|
||||
} Elf64_Chdr;
|
||||
|
||||
/* Legal values for ch_type (compression algorithm). */
|
||||
#define ELFCOMPRESS_ZLIB 1 /* ZLIB/DEFLATE algorithm. */
|
||||
#define ELFCOMPRESS_LOOS 0x60000000 /* Start of OS-specific. */
|
||||
#define ELFCOMPRESS_HIOS 0x6fffffff /* End of OS-specific. */
|
||||
#define ELFCOMPRESS_LOPROC 0x70000000 /* Start of processor-specific. */
|
||||
#define ELFCOMPRESS_HIPROC 0x7fffffff /* End of processor-specific. */
|
||||
#endif
|
||||
|
||||
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
|
||||
# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
|
||||
# define __deprecated_attribute__ __attribute__ ((__deprecated__))
|
||||
# define __pure_attribute__ __attribute__ ((__pure__))
|
||||
# define __const_attribute__ __attribute__ ((__const__))
|
||||
#else
|
||||
# define __nonnull_attribute__(...)
|
||||
# define __deprecated_attribute__
|
||||
# define __pure_attribute__
|
||||
# define __const_attribute__
|
||||
#endif
|
||||
|
||||
#if __GNUC__ < 4
|
||||
#define __noreturn_attribute__
|
||||
#else
|
||||
#define __noreturn_attribute__ __attribute__ ((noreturn))
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC_STDC_INLINE__
|
||||
# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
|
||||
#else
|
||||
# define __libdw_extern_inline extern __inline
|
||||
#endif
|
||||
|
||||
/* Known translation types. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_T_BYTE, /* unsigned char */
|
||||
ELF_T_ADDR, /* Elf32_Addr, Elf64_Addr, ... */
|
||||
ELF_T_DYN, /* Dynamic section record. */
|
||||
ELF_T_EHDR, /* ELF header. */
|
||||
ELF_T_HALF, /* Elf32_Half, Elf64_Half, ... */
|
||||
ELF_T_OFF, /* Elf32_Off, Elf64_Off, ... */
|
||||
ELF_T_PHDR, /* Program header. */
|
||||
ELF_T_RELA, /* Relocation entry with addend. */
|
||||
ELF_T_REL, /* Relocation entry. */
|
||||
ELF_T_SHDR, /* Section header. */
|
||||
ELF_T_SWORD, /* Elf32_Sword, Elf64_Sword, ... */
|
||||
ELF_T_SYM, /* Symbol record. */
|
||||
ELF_T_WORD, /* Elf32_Word, Elf64_Word, ... */
|
||||
ELF_T_XWORD, /* Elf32_Xword, Elf64_Xword, ... */
|
||||
ELF_T_SXWORD, /* Elf32_Sxword, Elf64_Sxword, ... */
|
||||
ELF_T_VDEF, /* Elf32_Verdef, Elf64_Verdef, ... */
|
||||
ELF_T_VDAUX, /* Elf32_Verdaux, Elf64_Verdaux, ... */
|
||||
ELF_T_VNEED, /* Elf32_Verneed, Elf64_Verneed, ... */
|
||||
ELF_T_VNAUX, /* Elf32_Vernaux, Elf64_Vernaux, ... */
|
||||
ELF_T_NHDR, /* Elf32_Nhdr, Elf64_Nhdr, ... */
|
||||
ELF_T_SYMINFO, /* Elf32_Syminfo, Elf64_Syminfo, ... */
|
||||
ELF_T_MOVE, /* Elf32_Move, Elf64_Move, ... */
|
||||
ELF_T_LIB, /* Elf32_Lib, Elf64_Lib, ... */
|
||||
ELF_T_GNUHASH, /* GNU-style hash section. */
|
||||
ELF_T_AUXV, /* Elf32_auxv_t, Elf64_auxv_t, ... */
|
||||
ELF_T_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
|
||||
/* Keep this the last entry. */
|
||||
ELF_T_NUM
|
||||
} Elf_Type;
|
||||
|
||||
/* Descriptor for data to be converted to or from memory format. */
|
||||
typedef struct
|
||||
{
|
||||
void *d_buf; /* Pointer to the actual data. */
|
||||
Elf_Type d_type; /* Type of this piece of data. */
|
||||
unsigned int d_version; /* ELF version. */
|
||||
size_t d_size; /* Size in bytes. */
|
||||
int64_t d_off; /* Offset into section. */
|
||||
size_t d_align; /* Alignment in section. */
|
||||
} Elf_Data;
|
||||
|
||||
|
||||
/* Commands for `...'. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_C_NULL, /* Nothing, terminate, or compute only. */
|
||||
ELF_C_READ, /* Read .. */
|
||||
ELF_C_RDWR, /* Read and write .. */
|
||||
ELF_C_WRITE, /* Write .. */
|
||||
ELF_C_CLR, /* Clear flag. */
|
||||
ELF_C_SET, /* Set flag. */
|
||||
ELF_C_FDDONE, /* Signal that file descriptor will not be
|
||||
used anymore. */
|
||||
ELF_C_FDREAD, /* Read rest of data so that file descriptor
|
||||
is not used anymore. */
|
||||
/* The following are extensions. */
|
||||
ELF_C_READ_MMAP, /* Read, but mmap the file if possible. */
|
||||
ELF_C_RDWR_MMAP, /* Read and write, with mmap. */
|
||||
ELF_C_WRITE_MMAP, /* Write, with mmap. */
|
||||
ELF_C_READ_MMAP_PRIVATE, /* Read, but memory is writable, results are
|
||||
not written to the file. */
|
||||
ELF_C_EMPTY, /* Copy basic file data but not the content. */
|
||||
/* Keep this the last entry. */
|
||||
ELF_C_NUM
|
||||
} Elf_Cmd;
|
||||
|
||||
|
||||
/* Flags for the ELF structures. */
|
||||
enum
|
||||
{
|
||||
ELF_F_DIRTY = 0x1,
|
||||
#define ELF_F_DIRTY ELF_F_DIRTY
|
||||
ELF_F_LAYOUT = 0x4,
|
||||
#define ELF_F_LAYOUT ELF_F_LAYOUT
|
||||
ELF_F_PERMISSIVE = 0x8
|
||||
#define ELF_F_PERMISSIVE ELF_F_PERMISSIVE
|
||||
};
|
||||
|
||||
/* Flags for elf_compress[_gnu]. */
|
||||
enum
|
||||
{
|
||||
ELF_CHF_FORCE = 0x1
|
||||
#define ELF_CHF_FORCE ELF_CHF_FORCE
|
||||
};
|
||||
|
||||
/* Identification values for recognized object files. */
|
||||
typedef enum
|
||||
{
|
||||
ELF_K_NONE, /* Unknown. */
|
||||
ELF_K_AR, /* Archive. */
|
||||
ELF_K_COFF, /* Stupid old COFF. */
|
||||
ELF_K_ELF, /* ELF file. */
|
||||
/* Keep this the last entry. */
|
||||
ELF_K_NUM
|
||||
} Elf_Kind;
|
||||
|
||||
|
||||
/* Archive member header. */
|
||||
typedef struct
|
||||
{
|
||||
char *ar_name; /* Name of archive member. */
|
||||
time_t ar_date; /* File date. */
|
||||
uid_t ar_uid; /* User ID. */
|
||||
gid_t ar_gid; /* Group ID. */
|
||||
mode_t ar_mode; /* File mode. */
|
||||
int64_t ar_size; /* File size. */
|
||||
char *ar_rawname; /* Original name of archive member. */
|
||||
} Elf_Arhdr;
|
||||
|
||||
|
||||
/* Archive symbol table entry. */
|
||||
typedef struct
|
||||
{
|
||||
char *as_name; /* Symbol name. */
|
||||
size_t as_off; /* Offset for this file in the archive. */
|
||||
unsigned long int as_hash; /* Hash value of the name. */
|
||||
} Elf_Arsym;
|
||||
|
||||
|
||||
/* Descriptor for the ELF file. */
|
||||
typedef struct Elf Elf;
|
||||
|
||||
/* Descriptor for ELF file section. */
|
||||
typedef struct Elf_Scn Elf_Scn;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Return descriptor for ELF file to work according to CMD. */
|
||||
extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
|
||||
|
||||
/* Create a clone of an existing ELF descriptor. */
|
||||
extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
|
||||
|
||||
/* Create descriptor for memory region. */
|
||||
extern Elf *elf_memory (char *__image, size_t __size);
|
||||
|
||||
/* Advance archive descriptor to next element. */
|
||||
extern Elf_Cmd elf_next (Elf *__elf);
|
||||
|
||||
/* Free resources allocated for ELF. */
|
||||
extern int elf_end (Elf *__elf);
|
||||
|
||||
/* Update ELF descriptor and write file to disk. */
|
||||
extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
|
||||
|
||||
/* Determine what kind of file is associated with ELF. */
|
||||
extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
|
||||
|
||||
/* Get the base offset for an object file. */
|
||||
extern int64_t elf_getbase (Elf *__elf);
|
||||
|
||||
|
||||
/* Retrieve file identification data. */
|
||||
extern char *elf_getident (Elf *__elf, size_t *__nbytes);
|
||||
|
||||
/* Retrieve class-dependent object file header. */
|
||||
extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
|
||||
|
||||
/* Create ELF header if none exists. */
|
||||
extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
|
||||
|
||||
/* Get the number of program headers in the ELF file. If the file uses
|
||||
more headers than can be represented in the e_phnum field of the ELF
|
||||
header the information from the sh_info field in the zeroth section
|
||||
header is used. */
|
||||
extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
|
||||
|
||||
/* Retrieve class-dependent program header table. */
|
||||
extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
|
||||
|
||||
/* Create ELF program header. */
|
||||
extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
|
||||
|
||||
|
||||
/* Get section at INDEX. */
|
||||
extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
|
||||
|
||||
/* Get section at OFFSET. */
|
||||
extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
|
||||
/* Similar bug this time the binary calls is ELFCLASS64. */
|
||||
extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
|
||||
|
||||
/* Get index of section. */
|
||||
extern size_t elf_ndxscn (Elf_Scn *__scn);
|
||||
|
||||
/* Get section with next section index. */
|
||||
extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
|
||||
|
||||
/* Create a new section and append it at the end of the table. */
|
||||
extern Elf_Scn *elf_newscn (Elf *__elf);
|
||||
|
||||
/* Get the section index of the extended section index table for the
|
||||
given symbol table. */
|
||||
extern int elf_scnshndx (Elf_Scn *__scn);
|
||||
|
||||
/* Get the number of sections in the ELF file. If the file uses more
|
||||
sections than can be represented in the e_shnum field of the ELF
|
||||
header the information from the sh_size field in the zeroth section
|
||||
header is used. */
|
||||
extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
|
||||
/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
|
||||
It was agreed to make the same functionality available under a different
|
||||
name and obsolete the old name. */
|
||||
extern int elf_getshnum (Elf *__elf, size_t *__dst)
|
||||
__deprecated_attribute__;
|
||||
|
||||
|
||||
/* Get the section index of the section header string table in the ELF
|
||||
file. If the index cannot be represented in the e_shnum field of
|
||||
the ELF header the information from the sh_link field in the zeroth
|
||||
section header is used. */
|
||||
extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
|
||||
/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
|
||||
It was agreed to make the same functionality available under a different
|
||||
name and obsolete the old name. */
|
||||
extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
|
||||
__deprecated_attribute__;
|
||||
|
||||
|
||||
/* Retrieve section header of ELFCLASS32 binary. */
|
||||
extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
|
||||
/* Similar for ELFCLASS64. */
|
||||
extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
|
||||
|
||||
/* Returns compression header for a section if section data is
|
||||
compressed. Returns NULL and sets elf_errno if the section isn't
|
||||
compressed or an error occurred. */
|
||||
extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
|
||||
extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
|
||||
|
||||
/* Compress or decompress the data of a section and adjust the section
|
||||
header.
|
||||
|
||||
elf_compress works by setting or clearing the SHF_COMPRESS flag
|
||||
from the section Shdr and will encode or decode a Elf32_Chdr or
|
||||
Elf64_Chdr at the start of the section data. elf_compress_gnu will
|
||||
encode or decode any section, but is traditionally only used for
|
||||
sections that have a name starting with ".debug" when
|
||||
uncompressed or ".zdebug" when compressed and stores just the
|
||||
uncompressed size. The GNU compression method is deprecated and
|
||||
should only be used for legacy support.
|
||||
|
||||
elf_compress takes a compression type that should be either zero to
|
||||
decompress or an ELFCOMPRESS algorithm to use for compression.
|
||||
Currently only ELFCOMPRESS_ZLIB is supported. elf_compress_gnu
|
||||
will compress in the traditional GNU compression format when
|
||||
compress is one and decompress the section data when compress is
|
||||
zero.
|
||||
|
||||
The FLAGS argument can be zero or ELF_CHF_FORCE. If FLAGS contains
|
||||
ELF_CHF_FORCE then it will always compress the section, even if
|
||||
that would not reduce the size of the data section (including the
|
||||
header). Otherwise elf_compress and elf_compress_gnu will compress
|
||||
the section only if the total data size is reduced.
|
||||
|
||||
On successful compression or decompression the function returns
|
||||
one. If (not forced) compression is requested and the data section
|
||||
would not actually reduce in size, the section is not actually
|
||||
compressed and zero is returned. Otherwise -1 is returned and
|
||||
elf_errno is set.
|
||||
|
||||
It is an error to request compression for a section that already
|
||||
has SHF_COMPRESSED set, or (for elf_compress) to request
|
||||
decompression for an section that doesn't have SHF_COMPRESSED set.
|
||||
It is always an error to call these functions on SHT_NOBITS
|
||||
sections or if the section has the SHF_ALLOC flag set.
|
||||
elf_compress_gnu will not check whether the section name starts
|
||||
with ".debug" or .zdebug". It is the responsibilty of the caller
|
||||
to make sure the deprecated GNU compression method is only called
|
||||
on correctly named sections (and to change the name of the section
|
||||
when using elf_compress_gnu).
|
||||
|
||||
All previous returned Shdrs and Elf_Data buffers are invalidated by
|
||||
this call and should no longer be accessed.
|
||||
|
||||
Note that although this changes the header and data returned it
|
||||
doesn't mark the section as dirty. To keep the changes when
|
||||
calling elf_update the section has to be flagged ELF_F_DIRTY. */
|
||||
extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
|
||||
extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
|
||||
|
||||
/* Set or clear flags for ELF file. */
|
||||
extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
/* Similarly for the ELF header. */
|
||||
extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
/* Similarly for the ELF program header. */
|
||||
extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
/* Similarly for the given ELF section. */
|
||||
extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
/* Similarly for the given ELF data. */
|
||||
extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
/* Similarly for the given ELF section header. */
|
||||
extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
|
||||
unsigned int __flags);
|
||||
|
||||
|
||||
/* Get data from section while translating from file representation to
|
||||
memory representation. The Elf_Data d_type is set based on the
|
||||
section type if known. Otherwise d_type is set to ELF_T_BYTE. If
|
||||
the section contains compressed data then d_type is always set to
|
||||
ELF_T_CHDR. */
|
||||
extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
|
||||
|
||||
/* Get uninterpreted section content. */
|
||||
extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
|
||||
|
||||
/* Create new data descriptor for section SCN. */
|
||||
extern Elf_Data *elf_newdata (Elf_Scn *__scn);
|
||||
|
||||
/* Get data translated from a chunk of the file contents as section data
|
||||
would be for TYPE. The resulting Elf_Data pointer is valid until
|
||||
elf_end (ELF) is called. */
|
||||
extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
|
||||
int64_t __offset, size_t __size,
|
||||
Elf_Type __type);
|
||||
|
||||
|
||||
/* Return pointer to string at OFFSET in section INDEX. */
|
||||
extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
|
||||
|
||||
|
||||
/* Return header of archive. */
|
||||
extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
|
||||
|
||||
/* Return offset in archive for current file ELF. */
|
||||
extern int64_t elf_getaroff (Elf *__elf);
|
||||
|
||||
/* Select archive element at OFFSET. */
|
||||
extern size_t elf_rand (Elf *__elf, size_t __offset);
|
||||
|
||||
/* Get symbol table of archive. */
|
||||
extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
|
||||
|
||||
|
||||
/* Control ELF descriptor. */
|
||||
extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
|
||||
|
||||
/* Retrieve uninterpreted file contents. */
|
||||
extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
|
||||
|
||||
|
||||
/* Return size of array of COUNT elements of the type denoted by TYPE
|
||||
in the external representation. The binary class is taken from ELF.
|
||||
The result is based on version VERSION of the ELF standard. */
|
||||
extern size_t elf32_fsize (Elf_Type __type, size_t __count,
|
||||
unsigned int __version)
|
||||
__const_attribute__;
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern size_t elf64_fsize (Elf_Type __type, size_t __count,
|
||||
unsigned int __version)
|
||||
__const_attribute__;
|
||||
|
||||
|
||||
/* Convert data structure from the representation in the file represented
|
||||
by ELF to their memory representation. */
|
||||
extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
|
||||
unsigned int __encode);
|
||||
/* Same for 64 bit class. */
|
||||
extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
|
||||
unsigned int __encode);
|
||||
|
||||
/* Convert data structure from to the representation in memory
|
||||
represented by ELF file representation. */
|
||||
extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
|
||||
unsigned int __encode);
|
||||
/* Same for 64 bit class. */
|
||||
extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
|
||||
unsigned int __encode);
|
||||
|
||||
|
||||
/* Return error code of last failing function call. This value is kept
|
||||
separately for each thread. */
|
||||
extern int elf_errno (void);
|
||||
|
||||
/* Return error string for ERROR. If ERROR is zero, return error string
|
||||
for most recent error or NULL is none occurred. If ERROR is -1 the
|
||||
behaviour is similar to the last case except that not NULL but a legal
|
||||
string is returned. */
|
||||
extern const char *elf_errmsg (int __error);
|
||||
|
||||
|
||||
/* Coordinate ELF library and application versions. */
|
||||
extern unsigned int elf_version (unsigned int __version);
|
||||
|
||||
/* Set fill bytes used to fill holes in data structures. */
|
||||
extern void elf_fill (int __fill);
|
||||
|
||||
/* Compute hash value. */
|
||||
extern unsigned long int elf_hash (const char *__string)
|
||||
__pure_attribute__;
|
||||
|
||||
/* Compute hash value using the GNU-specific hash function. */
|
||||
extern unsigned long int elf_gnu_hash (const char *__string)
|
||||
__pure_attribute__;
|
||||
|
||||
|
||||
/* Compute simple checksum from permanent parts of the ELF file. */
|
||||
extern long int elf32_checksum (Elf *__elf);
|
||||
/* Similar but this time the binary calls is ELFCLASS64. */
|
||||
extern long int elf64_checksum (Elf *__elf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* libelf.h */
|
||||
@@ -0,0 +1,330 @@
|
||||
/* Abstract description of component ELF types.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* ELF header. */
|
||||
#define Ehdr(Bits, Ext) \
|
||||
START (Bits, Ehdr, Ext##Ehdr) \
|
||||
TYPE_EXTRA (unsigned char e_ident[EI_NIDENT];) \
|
||||
TYPE_XLATE (memmove (tdest->e_ident, tsrc->e_ident, EI_NIDENT);) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_type) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_machine) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), e_version) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Addr), e_entry) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Off), e_phoff) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Off), e_shoff) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), e_flags) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_ehsize) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_phentsize) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_phnum) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_shentsize) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_shnum) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), e_shstrndx) \
|
||||
END (Bits, Ext##Ehdr)
|
||||
|
||||
#define Ehdr32(Ext) \
|
||||
Ehdr(32, Ext)
|
||||
#define Ehdr64(Ext) \
|
||||
Ehdr(64, Ext)
|
||||
|
||||
|
||||
/* Program header. */
|
||||
#define Phdr32(Ext) \
|
||||
START (32, Phdr, Ext##Phdr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), p_type) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Off), p_offset) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), p_vaddr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), p_paddr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), p_filesz) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), p_memsz) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), p_flags) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), p_align) \
|
||||
END (32, Ext##Phdr)
|
||||
#define Phdr64(Ext) \
|
||||
START (64, Phdr, Ext##Phdr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), p_type) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), p_flags) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Off), p_offset) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), p_vaddr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), p_paddr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), p_filesz) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), p_memsz) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), p_align) \
|
||||
END (64, Ext##Phdr)
|
||||
|
||||
|
||||
/* Section header. */
|
||||
#define Shdr32(Ext) \
|
||||
START (32, Shdr, Ext##Shdr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_name) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_type) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_flags) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), sh_addr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Off), sh_offset) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_size) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_link) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_info) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_addralign) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), sh_entsize) \
|
||||
END (32, Ext##Shdr)
|
||||
#define Shdr64(Ext) \
|
||||
START (64, Shdr, Ext##Shdr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), sh_name) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), sh_type) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), sh_flags) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), sh_addr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Off), sh_offset) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), sh_size) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), sh_link) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), sh_info) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), sh_addralign) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), sh_entsize) \
|
||||
END (64, Ext##Shdr)
|
||||
|
||||
|
||||
/* Symbol table. */
|
||||
#define Sym32(Ext) \
|
||||
START (32, Sym, Ext##Sym) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), st_name) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), st_value) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), st_size) \
|
||||
TYPE_EXTRA (unsigned char st_info;) \
|
||||
TYPE_XLATE (tdest->st_info = tsrc->st_info;) \
|
||||
TYPE_EXTRA (unsigned char st_other;) \
|
||||
TYPE_XLATE (tdest->st_other = tsrc->st_other;) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Half), st_shndx) \
|
||||
END (32, Ext##Sym)
|
||||
#define Sym64(Ext) \
|
||||
START (64, Sym, Ext##Sym) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), st_name) \
|
||||
TYPE_EXTRA (unsigned char st_info;) \
|
||||
TYPE_XLATE (tdest->st_info = tsrc->st_info;) \
|
||||
TYPE_EXTRA (unsigned char st_other;) \
|
||||
TYPE_XLATE (tdest->st_other = tsrc->st_other;) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Half), st_shndx) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), st_value) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), st_size) \
|
||||
END (64, Ext##Sym)
|
||||
|
||||
|
||||
/* Relocation. */
|
||||
#define Rel32(Ext) \
|
||||
START (32, Rel, Ext##Rel) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), r_offset) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), r_info) \
|
||||
END (32, Ext##Rel)
|
||||
#define Rel64(Ext) \
|
||||
START (64, Rel, Ext##Rel) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), r_offset) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), r_info) \
|
||||
END (64, Ext##Rel)
|
||||
|
||||
#define Rela32(Ext) \
|
||||
START (32, Rela, Ext##Rela) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Addr), r_offset) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), r_info) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Sword), r_addend) \
|
||||
END (32, Ext##Rela)
|
||||
#define Rela64(Ext) \
|
||||
START (64, Rela, Ext##Rela) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Addr), r_offset) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), r_info) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Sxword), r_addend) \
|
||||
END (64, Ext##Rela)
|
||||
|
||||
|
||||
/* Note entry header. */
|
||||
#define Note(Bits, Ext) \
|
||||
START (Bits, Nhdr, Ext##Nhdr) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), n_namesz) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), n_descsz) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), n_type) \
|
||||
END (Bits, Ext##Nhdr)
|
||||
|
||||
#define Note32(Ext) \
|
||||
Note (32, Ext)
|
||||
#define Note64(Ext) \
|
||||
Note (64, Ext)
|
||||
|
||||
|
||||
/* Dynamic section data. */
|
||||
#define Dyn32(Ext) \
|
||||
START (32, Dyn, Ext##Dyn) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Sword), d_tag) \
|
||||
TYPE_EXTRA (union {) \
|
||||
TYPE_EXTRA (ElfW2(32, Ext##Word) d_val;) \
|
||||
TYPE_EXTRA (ElfW2(32, Ext##Addr) d_ptr;) \
|
||||
TYPE_XLATE (Elf32_cvt_Addr1 (&tdest->d_un.d_val, &tsrc->d_un.d_val);) \
|
||||
TYPE_EXTRA (ElfW2(32, Ext##Off) d_off;) \
|
||||
TYPE_EXTRA (} d_un;) \
|
||||
END (32, Ext##Dyn)
|
||||
#define Dyn64(Ext) \
|
||||
START (64, Dyn, Ext##Dyn) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), d_tag) \
|
||||
TYPE_EXTRA (union {) \
|
||||
TYPE_EXTRA (ElfW2(64, Ext##Xword) d_val;) \
|
||||
TYPE_EXTRA (ElfW2(64, Ext##Addr) d_ptr;) \
|
||||
TYPE_XLATE (Elf64_cvt_Addr1 (&tdest->d_un.d_val, &tsrc->d_un.d_val);) \
|
||||
TYPE_EXTRA (} d_un;) \
|
||||
END (64, Ext##Dyn)
|
||||
|
||||
|
||||
#ifndef GENERATE_CONVERSION
|
||||
/* Version definitions. */
|
||||
# define Verdef(Bits, Ext) \
|
||||
START (Bits, Verdef, Ext##Verdef) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vd_version) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vd_flags) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vd_ndx) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vd_cnt) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vd_hash) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vd_aux) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vd_next) \
|
||||
END (Bits, Ext##Verdef)
|
||||
|
||||
# define Verdef32(Ext) \
|
||||
Verdef (32, Ext)
|
||||
# define Verdef64(Ext) \
|
||||
Verdef (64, Ext)
|
||||
|
||||
# define Verdaux(Bits, Ext) \
|
||||
START (Bits, Verdaux, Ext##Verdaux) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vda_name) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vda_next) \
|
||||
END (Bits, Ext##Verdaux)
|
||||
|
||||
# define Verdaux32(Ext) \
|
||||
Verdaux (32, Ext)
|
||||
# define Verdaux64(Ext) \
|
||||
Verdaux (64, Ext)
|
||||
|
||||
/* Required versions. */
|
||||
# define Verneed(Bits, Ext) \
|
||||
START (Bits, Verneed, Ext##Verneed) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vn_version) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vn_cnt) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vn_file) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vn_aux) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vn_next) \
|
||||
END (Bits, Ext##Verneed)
|
||||
|
||||
# define Verneed32(Ext) \
|
||||
Verneed (32, Ext)
|
||||
# define Verneed64(Ext) \
|
||||
Verneed (64, Ext)
|
||||
|
||||
# define Vernaux(Bits, Ext) \
|
||||
START (Bits, Vernaux, Ext##Vernaux) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vna_hash) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vna_flags) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), vna_other) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vna_name) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), vna_next) \
|
||||
END (Bits, Ext##Vernaux)
|
||||
|
||||
# define Vernaux32(Ext) \
|
||||
Vernaux (32, Ext)
|
||||
# define Vernaux64(Ext) \
|
||||
Vernaux (64, Ext)
|
||||
#endif
|
||||
|
||||
/* Symbol information. */
|
||||
#define Syminfo(Bits, Ext) \
|
||||
START (Bits, Syminfo, Ext##Syminfo) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), si_boundto) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), si_flags) \
|
||||
END (Bits, Ext##Syminfo)
|
||||
|
||||
#define Syminfo32(Ext) \
|
||||
Syminfo (32, Ext)
|
||||
#define Syminfo64(Ext) \
|
||||
Syminfo (64, Ext)
|
||||
|
||||
/* Move information. */
|
||||
#define Move(Bits, Ext) \
|
||||
START (Bits, Move, Ext##Move) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Xword), m_value) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Xword), m_info) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Xword), m_poffset) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), m_repeat) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Half), m_stride) \
|
||||
END (Bits, Ext##Move)
|
||||
|
||||
#define Move32(Ext) \
|
||||
Move (32, Ext)
|
||||
#define Move64(Ext) \
|
||||
Move (64, Ext)
|
||||
|
||||
#define Lib(Bits, Ext) \
|
||||
START (Bits, Lib, Ext##Lib) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), l_name) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), l_time_stamp) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), l_checksum) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), l_version) \
|
||||
TYPE_NAME (ElfW2(Bits, Ext##Word), l_flags) \
|
||||
END (Bits, Ext##Lib)
|
||||
|
||||
#define Lib32(Ext) \
|
||||
Lib (32, Ext)
|
||||
#define Lib64(Ext) \
|
||||
Lib (64, Ext)
|
||||
|
||||
#define auxv_t32(Ext) \
|
||||
START (32, auxv_t, Ext##auxv_t) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), a_type) \
|
||||
TYPE_EXTRA (union {) \
|
||||
TYPE_EXTRA (ElfW2(32, Ext##Word) a_val;) \
|
||||
TYPE_XLATE (Elf32_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);) \
|
||||
TYPE_EXTRA (} a_un;) \
|
||||
END (32, Ext##auxv_t)
|
||||
#define auxv_t64(Ext) \
|
||||
START (64, auxv_t, Ext##auxv_t) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), a_type) \
|
||||
TYPE_EXTRA (union {) \
|
||||
TYPE_EXTRA (ElfW2(64, Ext##Xword) a_val;) \
|
||||
TYPE_XLATE (Elf64_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);) \
|
||||
TYPE_EXTRA (} a_un;) \
|
||||
END (64, Ext##auxv_t)
|
||||
|
||||
/* Note that there is actual compression data right after the Chdr.
|
||||
So we also have a separate conversion function for the whole
|
||||
section. */
|
||||
#define Chdr32(Ext) \
|
||||
START (32, Chdr, Ext##Chdr) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), ch_type) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), ch_size) \
|
||||
TYPE_NAME (ElfW2(32, Ext##Word), ch_addralign) \
|
||||
END (32, Ext##Chdr)
|
||||
|
||||
#define Chdr64(Ext) \
|
||||
START (64, Chdr, Ext##Chdr) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), ch_type) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Word), ch_reserved) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), ch_size) \
|
||||
TYPE_NAME (ElfW2(64, Ext##Xword), ch_addralign) \
|
||||
END (64, Ext##Chdr)
|
||||
@@ -0,0 +1,33 @@
|
||||
#include "common.h"
|
||||
|
||||
/* These functions convert a while section, one Chdr plus compression data. */
|
||||
|
||||
static void
|
||||
Elf32_cvt_chdr (void *dest, const void *src, size_t len, int encode)
|
||||
{
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
/* Move everything over, if necessary, we only need to xlate the
|
||||
header, not the compressed data following it. */
|
||||
if (dest != src)
|
||||
memmove (dest, src, len);
|
||||
|
||||
if (len >= sizeof (Elf32_Chdr))
|
||||
Elf32_cvt_Chdr (dest, src, sizeof (Elf32_Chdr), encode);
|
||||
}
|
||||
|
||||
static void
|
||||
Elf64_cvt_chdr (void *dest, const void *src, size_t len, int encode)
|
||||
{
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
/* Move everything over, if necessary, we only need to xlate the
|
||||
header, not the compressed data following it. */
|
||||
if (dest != src)
|
||||
memmove (dest, src, len);
|
||||
|
||||
if (len >= sizeof (Elf64_Chdr))
|
||||
Elf64_cvt_Chdr (dest, src, sizeof (Elf64_Chdr), encode);
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/* Common definitions for handling files in memory or only on disk.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2005, 2008 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H 1
|
||||
|
||||
#include <ar.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "portable_endian.h"
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
static inline Elf_Kind
|
||||
__attribute__ ((unused))
|
||||
determine_kind (void *buf, size_t len)
|
||||
{
|
||||
/* First test for an archive. */
|
||||
if (len >= SARMAG && memcmp (buf, ARMAG, SARMAG) == 0)
|
||||
return ELF_K_AR;
|
||||
|
||||
/* Next try ELF files. */
|
||||
if (len >= EI_NIDENT && memcmp (buf, ELFMAG, SELFMAG) == 0)
|
||||
{
|
||||
/* Could be an ELF file. */
|
||||
int eclass = (int) ((unsigned char *) buf)[EI_CLASS];
|
||||
int data = (int) ((unsigned char *) buf)[EI_DATA];
|
||||
int version = (int) ((unsigned char *) buf)[EI_VERSION];
|
||||
|
||||
if (eclass > ELFCLASSNONE && eclass < ELFCLASSNUM
|
||||
&& data > ELFDATANONE && data < ELFDATANUM
|
||||
&& version > EV_NONE && version < EV_NUM)
|
||||
return ELF_K_ELF;
|
||||
}
|
||||
|
||||
/* We do not know this file type. */
|
||||
return ELF_K_NONE;
|
||||
}
|
||||
|
||||
|
||||
/* Allocate an Elf descriptor and fill in the generic information. */
|
||||
static inline Elf *
|
||||
__attribute__ ((unused))
|
||||
allocate_elf (int fildes, void *map_address, off_t offset, size_t maxsize,
|
||||
Elf_Cmd cmd, Elf *parent, Elf_Kind kind, size_t extra)
|
||||
{
|
||||
Elf *result = (Elf *) calloc (1, sizeof (Elf) + extra);
|
||||
if (result == NULL)
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
else
|
||||
{
|
||||
result->kind = kind;
|
||||
result->ref_count = 1;
|
||||
result->cmd = cmd;
|
||||
result->fildes = fildes;
|
||||
result->start_offset = offset;
|
||||
result->maximum_size = maxsize;
|
||||
result->map_address = map_address;
|
||||
result->parent = parent;
|
||||
|
||||
rwlock_init (result->lock);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* Acquire lock for the descriptor and all children. */
|
||||
static void
|
||||
__attribute__ ((unused))
|
||||
libelf_acquire_all (Elf *elf)
|
||||
{
|
||||
rwlock_wrlock (elf->lock);
|
||||
|
||||
if (elf->kind == ELF_K_AR)
|
||||
{
|
||||
Elf *child = elf->state.ar.children;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (child->ref_count != 0)
|
||||
libelf_acquire_all (child);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Release own lock and those of the children. */
|
||||
static void
|
||||
__attribute__ ((unused))
|
||||
libelf_release_all (Elf *elf)
|
||||
{
|
||||
if (elf->kind == ELF_K_AR)
|
||||
{
|
||||
Elf *child = elf->state.ar.children;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
if (child->ref_count != 0)
|
||||
libelf_release_all (child);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
|
||||
rwlock_unlock (elf->lock);
|
||||
}
|
||||
|
||||
|
||||
/* Macro to convert endianess in place. It determines the function it
|
||||
has to use itself. */
|
||||
#define CONVERT(Var) \
|
||||
(Var) = (sizeof (Var) == 1 \
|
||||
? (unsigned char) (Var) \
|
||||
: (sizeof (Var) == 2 \
|
||||
? bswap_16 (Var) \
|
||||
: (sizeof (Var) == 4 \
|
||||
? bswap_32 (Var) \
|
||||
: bswap_64 (Var))))
|
||||
|
||||
#define CONVERT_TO(Dst, Var) \
|
||||
(Dst) = (sizeof (Var) == 1 \
|
||||
? (unsigned char) (Var) \
|
||||
: (sizeof (Var) == 2 \
|
||||
? bswap_16 (Var) \
|
||||
: (sizeof (Var) == 4 \
|
||||
? bswap_32 (Var) \
|
||||
: bswap_64 (Var))))
|
||||
|
||||
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define MY_ELFDATA ELFDATA2LSB
|
||||
#else
|
||||
# define MY_ELFDATA ELFDATA2MSB
|
||||
#endif
|
||||
|
||||
#endif /* common.h */
|
||||
@@ -0,0 +1,195 @@
|
||||
/* Configuration definitions.
|
||||
Copyright (C) 2008, 2009 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef EU_CONFIG_H
|
||||
#define EU_CONFIG_H 1
|
||||
|
||||
#ifdef USE_LOCKS
|
||||
# include <pthread.h>
|
||||
# include <assert.h>
|
||||
# define rwlock_define(class,name) class pthread_rwlock_t name
|
||||
# define RWLOCK_CALL(call) \
|
||||
({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
|
||||
# define rwlock_init(lock) RWLOCK_CALL (init (&lock, NULL))
|
||||
# define rwlock_fini(lock) RWLOCK_CALL (destroy (&lock))
|
||||
# define rwlock_rdlock(lock) RWLOCK_CALL (rdlock (&lock))
|
||||
# define rwlock_wrlock(lock) RWLOCK_CALL (wrlock (&lock))
|
||||
# define rwlock_unlock(lock) RWLOCK_CALL (unlock (&lock))
|
||||
#else
|
||||
/* Eventually we will allow multi-threaded applications to use the
|
||||
libraries. Therefore we will add the necessary locking although
|
||||
the macros used expand to nothing for now. */
|
||||
# define rwlock_define(class,name) class int name
|
||||
# define rwlock_init(lock) ((void) (lock))
|
||||
# define rwlock_fini(lock) ((void) (lock))
|
||||
# define rwlock_rdlock(lock) ((void) (lock))
|
||||
# define rwlock_wrlock(lock) ((void) (lock))
|
||||
# define rwlock_unlock(lock) ((void) (lock))
|
||||
#endif /* USE_LOCKS */
|
||||
|
||||
/* gettext helper macro. */
|
||||
#define N_(Str) Str
|
||||
|
||||
/* Compiler-specific definitions. */
|
||||
//#define strong_alias(name, aliasname) \
|
||||
// extern __typeof (name) aliasname __attribute__ ((alias (#name)));
|
||||
|
||||
#define strong_alias(name, aliasname)
|
||||
|
||||
#ifdef __i386__
|
||||
# define internal_function __attribute__ ((regparm (3), stdcall))
|
||||
#else
|
||||
# define internal_function /* nothing */
|
||||
#endif
|
||||
|
||||
#define internal_strong_alias(name, aliasname) \
|
||||
extern __typeof (name) aliasname __attribute__ ((alias (#name))) internal_function;
|
||||
|
||||
#define attribute_hidden \
|
||||
__attribute__ ((visibility ("hidden")))
|
||||
|
||||
/* Define ALLOW_UNALIGNED if the architecture allows operations on
|
||||
unaligned memory locations. */
|
||||
#define SANITIZE_UNDEFINED 1
|
||||
#if (defined __i386__ || defined __x86_64__) && ! CHECK_UNDEFINED
|
||||
# define ALLOW_UNALIGNED 1
|
||||
#else
|
||||
# define ALLOW_UNALIGNED 0
|
||||
#endif
|
||||
|
||||
#if DEBUGPRED
|
||||
# ifdef __x86_64__
|
||||
asm (".section predict_data, \"aw\"; .previous\n"
|
||||
".section predict_line, \"a\"; .previous\n"
|
||||
".section predict_file, \"a\"; .previous");
|
||||
# ifndef PIC
|
||||
# define debugpred__(e, E) \
|
||||
({ long int _e = !!(e); \
|
||||
asm volatile (".pushsection predict_data; ..predictcnt%=: .quad 0; .quad 0\n" \
|
||||
".section predict_line; .quad %c1\n" \
|
||||
".section predict_file; .quad %c2; .popsection\n" \
|
||||
"addq $1,..predictcnt%=(,%0,8)" \
|
||||
: : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \
|
||||
__builtin_expect (_e, E); \
|
||||
})
|
||||
# endif
|
||||
# elif defined __i386__
|
||||
asm (".section predict_data, \"aw\"; .previous\n"
|
||||
".section predict_line, \"a\"; .previous\n"
|
||||
".section predict_file, \"a\"; .previous");
|
||||
# ifndef PIC
|
||||
# define debugpred__(e, E) \
|
||||
({ long int _e = !!(e); \
|
||||
asm volatile (".pushsection predict_data; ..predictcnt%=: .long 0; .long 0\n" \
|
||||
".section predict_line; .long %c1\n" \
|
||||
".section predict_file; .long %c2; .popsection\n" \
|
||||
"incl ..predictcnt%=(,%0,8)" \
|
||||
: : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \
|
||||
__builtin_expect (_e, E); \
|
||||
})
|
||||
# endif
|
||||
# endif
|
||||
# ifdef debugpred__
|
||||
# define unlikely(e) debugpred__ (e,0)
|
||||
# define likely(e) debugpred__ (e,1)
|
||||
# endif
|
||||
#endif
|
||||
#ifndef likely
|
||||
# define unlikely(expr) __builtin_expect (!!(expr), 0)
|
||||
# define likely(expr) __builtin_expect (!!(expr), 1)
|
||||
#endif
|
||||
|
||||
#define obstack_calloc(ob, size) \
|
||||
({ size_t _s = (size); memset (obstack_alloc (ob, _s), '\0', _s); })
|
||||
#define obstack_strdup(ob, str) \
|
||||
({ const char *_s = (str); obstack_copy0 (ob, _s, strlen (_s)); })
|
||||
#define obstack_strndup(ob, str, n) \
|
||||
({ const char *_s = (str); obstack_copy0 (ob, _s, strnlen (_s, n)); })
|
||||
|
||||
#if __STDC_VERSION__ >= 199901L
|
||||
# define flexarr_size /* empty */
|
||||
#else
|
||||
# define flexarr_size 0
|
||||
#endif
|
||||
|
||||
/* Calling conventions. */
|
||||
#ifdef __i386__
|
||||
# define CALLING_CONVENTION regparm (3), stdcall
|
||||
# define AND_CALLING_CONVENTION , regparm (3), stdcall
|
||||
#else
|
||||
# define CALLING_CONVENTION
|
||||
# define AND_CALLING_CONVENTION
|
||||
#endif
|
||||
|
||||
/* Avoid PLT entries. */
|
||||
#ifdef PIC
|
||||
# define INTUSE(name) _INTUSE(name)
|
||||
# define _INTUSE(name) __##name##_internal
|
||||
# define INTDEF(name) _INTDEF(name)
|
||||
# define _INTDEF(name) \
|
||||
extern __typeof__ (name) __##name##_internal __attribute__ ((alias (#name)));
|
||||
# define INTDECL(name) _INTDECL(name)
|
||||
# define _INTDECL(name) \
|
||||
extern __typeof__ (name) __##name##_internal attribute_hidden;
|
||||
#else
|
||||
# define INTUSE(name) name
|
||||
# define INTDEF(name) /* empty */
|
||||
# define INTDECL(name) /* empty */
|
||||
#endif
|
||||
|
||||
/* This macro is used by the tests conditionalize for standalone building. */
|
||||
#define ELFUTILS_HEADER(name) <lib##name.h>
|
||||
|
||||
|
||||
#ifdef SYMBOL_VERSIONING
|
||||
# define OLD_VERSION(name, version) \
|
||||
asm (".globl _compat." #version "." #name "\n" \
|
||||
"_compat." #version "." #name " = " #name "\n" \
|
||||
".symver _compat." #version "." #name "," #name "@" #version);
|
||||
# define NEW_VERSION(name, version) \
|
||||
asm (".symver " #name "," #name "@@@" #version);
|
||||
# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \
|
||||
asm (".symver _compat." #version "." #name "," #name "@" #version); \
|
||||
__typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \
|
||||
asm ("_compat." #version "." #name);
|
||||
# define COMPAT_VERSION(name, version, prefix) \
|
||||
asm (".symver _compat." #version "." #name "," #name "@" #version); \
|
||||
__typeof (name) _compat_##prefix##_##name asm ("_compat." #version "." #name);
|
||||
#else
|
||||
# define OLD_VERSION(name, version) /* Nothing for static linking. */
|
||||
# define NEW_VERSION(name, version) /* Nothing for static linking. */
|
||||
# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \
|
||||
error "should use #ifdef SYMBOL_VERSIONING"
|
||||
# define COMPAT_VERSION(name, version, prefix) error "should use #ifdef SYMBOL_VERSIONING"
|
||||
#endif
|
||||
|
||||
#define bswap_16(x) __builtin_bswap16(x)
|
||||
#define bswap_32(x) __builtin_bswap32(x)
|
||||
#define bswap_64(x) __builtin_bswap64(x)
|
||||
|
||||
#endif /* eu-config.h */
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Copyright (C) 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "system.h"
|
||||
|
||||
|
||||
/* Table computed with Mark Adler's makecrc.c utility. */
|
||||
static const uint32_t crc32_table[256] =
|
||||
{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
|
||||
0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
|
||||
0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
|
||||
0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
|
||||
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
|
||||
0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
|
||||
0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
|
||||
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
|
||||
0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
|
||||
0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
|
||||
0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
|
||||
0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
|
||||
0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
|
||||
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
|
||||
0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
|
||||
0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
|
||||
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
|
||||
0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
|
||||
0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
|
||||
0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
|
||||
0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
|
||||
0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
|
||||
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
|
||||
0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
|
||||
0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
|
||||
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
|
||||
0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
|
||||
0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
|
||||
0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
|
||||
0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
|
||||
0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
|
||||
0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
|
||||
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
|
||||
0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
|
||||
0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
|
||||
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
|
||||
0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
|
||||
0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
|
||||
0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
|
||||
0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
|
||||
0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t
|
||||
crc32 (uint32_t crc, unsigned char *buf, size_t len)
|
||||
{
|
||||
unsigned char *end;
|
||||
|
||||
crc = ~crc;
|
||||
for (end = buf + len; buf < end; ++buf)
|
||||
crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
|
||||
return ~crc;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/* Compute hash value for given string according to ELF standard.
|
||||
Copyright (C) 1995-2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _DL_HASH_H
|
||||
#define _DL_HASH_H 1
|
||||
|
||||
|
||||
/* This is the hashing function specified by the ELF ABI. In the
|
||||
first five operations no overflow is possible so we optimized it a
|
||||
bit. */
|
||||
static unsigned int
|
||||
__attribute__ ((unused))
|
||||
_dl_elf_hash (const char *name_arg)
|
||||
{
|
||||
const unsigned char *name = (const unsigned char *) name_arg;
|
||||
unsigned long int hash = *name;
|
||||
if (hash != 0 && name[1] != '\0')
|
||||
{
|
||||
hash = (hash << 4) + name[1];
|
||||
if (name[2] != '\0')
|
||||
{
|
||||
hash = (hash << 4) + name[2];
|
||||
if (name[3] != '\0')
|
||||
{
|
||||
hash = (hash << 4) + name[3];
|
||||
if (name[4] != '\0')
|
||||
{
|
||||
hash = (hash << 4) + name[4];
|
||||
name += 5;
|
||||
while (*name != '\0')
|
||||
{
|
||||
unsigned long int hi;
|
||||
hash = (hash << 4) + *name++;
|
||||
hi = hash & 0xf0000000;
|
||||
|
||||
/* The algorithm specified in the ELF ABI is as
|
||||
follows:
|
||||
|
||||
if (hi != 0)
|
||||
hash ^= hi >> 24;
|
||||
|
||||
hash &= ~hi;
|
||||
|
||||
But the following is equivalent and a lot
|
||||
faster, especially on modern processors. */
|
||||
|
||||
hash ^= hi >> 24;
|
||||
}
|
||||
|
||||
/* Second part of the modified formula. This
|
||||
operation can be lifted outside the loop. */
|
||||
hash &= 0x0fffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
#endif /* dl-hash.h */
|
||||
@@ -0,0 +1,80 @@
|
||||
/* Accumulation of various pieces of knowledge about ELF.
|
||||
Copyright (C) 2000-2012, 2014, 2016 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _ELF_KNOWLEDGE_H
|
||||
#define _ELF_KNOWLEDGE_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
/* Test whether a section can be stripped or not. */
|
||||
#define SECTION_STRIP_P(shdr, name, remove_comment) \
|
||||
/* Sections which are allocated are not removed. */ \
|
||||
(((shdr)->sh_flags & SHF_ALLOC) == 0 \
|
||||
/* We never remove .note sections. */ \
|
||||
&& (shdr)->sh_type != SHT_NOTE \
|
||||
&& (((shdr)->sh_type) != SHT_PROGBITS \
|
||||
/* Never remove .gnu.warning.* sections. */ \
|
||||
|| (name != NULL \
|
||||
&& strncmp (name, ".gnu.warning.", sizeof ".gnu.warning." - 1) != 0\
|
||||
/* We remove .comment sections only if explicitly told to do so. */\
|
||||
&& (remove_comment \
|
||||
|| strcmp (name, ".comment") != 0))))
|
||||
|
||||
|
||||
/* Test whether `sh_info' field in section header contains a section
|
||||
index. There are two kinds of sections doing this:
|
||||
|
||||
- the sections containing relocation information reference in this
|
||||
field the section to which the relocations apply;
|
||||
|
||||
- section with the SHF_INFO_LINK flag set to signal that `sh_info'
|
||||
references a section. This allows correct handling of unknown
|
||||
sections. */
|
||||
#define SH_INFO_LINK_P(Shdr) \
|
||||
((Shdr)->sh_type == SHT_REL || (Shdr)->sh_type == SHT_RELA \
|
||||
|| ((Shdr)->sh_flags & SHF_INFO_LINK) != 0)
|
||||
|
||||
|
||||
/* Size of an entry in the hash table. The ELF specification says all
|
||||
entries are regardless of platform 32-bits in size. Early 64-bit
|
||||
ports (namely Alpha for Linux) got this wrong. The wording was not
|
||||
clear.
|
||||
|
||||
Several years later the ABI for the 64-bit S390s was developed.
|
||||
Many things were copied from the IA-64 ABI (which uses the correct
|
||||
32-bit entry size) but what do these people do? They use 64-bit
|
||||
entries. It is really shocking to see what kind of morons are out
|
||||
there. And even worse: they are allowed to design ABIs. */
|
||||
#define SH_ENTSIZE_HASH(Ehdr) \
|
||||
((Ehdr)->e_machine == EM_ALPHA \
|
||||
|| ((Ehdr)->e_machine == EM_S390 \
|
||||
&& (Ehdr)->e_ident[EI_CLASS] == ELFCLASS64) ? 8 : 4)
|
||||
|
||||
#endif /* elf-knowledge.h */
|
||||
@@ -0,0 +1,168 @@
|
||||
/* Compute simple checksum from permanent parts of the ELF file.
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2009, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gelf.h"
|
||||
#include "libelfP.h"
|
||||
#include "elf-knowledge.h"
|
||||
#include "portable_endian.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
#define process_block(crc, data) \
|
||||
__libelf_crc32 (crc, data->d_buf, data->d_size)
|
||||
|
||||
|
||||
long int
|
||||
elfw2(LIBELFBITS,checksum) (Elf *elf)
|
||||
{
|
||||
size_t shstrndx;
|
||||
Elf_Scn *scn;
|
||||
long int result = 0;
|
||||
unsigned char *ident;
|
||||
bool same_byte_order;
|
||||
|
||||
if (elf == NULL)
|
||||
return -1l;
|
||||
|
||||
/* Find the section header string table. */
|
||||
if (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0)
|
||||
{
|
||||
/* This can only happen if the ELF handle is not for real. */
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return -1l;
|
||||
}
|
||||
|
||||
/* Determine whether the byte order of the file and that of the host
|
||||
is the same. */
|
||||
ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident;
|
||||
same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
|
||||
&& __BYTE_ORDER == __LITTLE_ENDIAN)
|
||||
|| (ident[EI_DATA] == ELFDATA2MSB
|
||||
&& __BYTE_ORDER == __BIG_ENDIAN));
|
||||
|
||||
/* If we don't have native byte order, we will likely need to
|
||||
convert the data with xlate functions. We do it upfront instead
|
||||
of relocking mid-iteration. */
|
||||
if (!likely (same_byte_order))
|
||||
rwlock_wrlock (elf->lock);
|
||||
else
|
||||
rwlock_rdlock (elf->lock);
|
||||
|
||||
/* Iterate over all sections to find those which are not strippable. */
|
||||
scn = NULL;
|
||||
while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL)
|
||||
{
|
||||
GElf_Shdr shdr_mem;
|
||||
GElf_Shdr *shdr;
|
||||
Elf_Data *data;
|
||||
|
||||
/* Get the section header. */
|
||||
shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem);
|
||||
if (shdr == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
|
||||
result = -1l;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (SECTION_STRIP_P (shdr,
|
||||
INTUSE(elf_strptr) (elf, shstrndx, shdr->sh_name),
|
||||
true))
|
||||
/* The section can be stripped. Don't use it. */
|
||||
continue;
|
||||
|
||||
/* Do not look at NOBITS sections. */
|
||||
if (shdr->sh_type == SHT_NOBITS)
|
||||
continue;
|
||||
|
||||
/* To compute the checksum we need to get to the data. For
|
||||
repeatable results we must use the external format. The data
|
||||
we get with 'elf'getdata' might be changed for endianess
|
||||
reasons. Therefore we use 'elf_rawdata' if possible. But
|
||||
this function can fail if the data was constructed by the
|
||||
program. In this case we have to use 'elf_getdata' and
|
||||
eventually convert the data to the external format. */
|
||||
data = INTUSE(elf_rawdata) (scn, NULL);
|
||||
if (data != NULL)
|
||||
{
|
||||
/* The raw data is available. */
|
||||
result = process_block (result, data);
|
||||
|
||||
/* Maybe the user added more data. These blocks cannot be
|
||||
read using 'elf_rawdata'. Simply proceed with looking
|
||||
for more data block with 'elf_getdata'. */
|
||||
}
|
||||
|
||||
/* Iterate through the list of data blocks. */
|
||||
while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
|
||||
/* If the file byte order is the same as the host byte order
|
||||
process the buffer directly. If the data is just a stream
|
||||
of bytes which the library will not convert we can use it
|
||||
as well. */
|
||||
if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
|
||||
result = process_block (result, data);
|
||||
else
|
||||
{
|
||||
/* Convert the data to file byte order. */
|
||||
if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA])
|
||||
== NULL)
|
||||
{
|
||||
result = -1l;
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = process_block (result, data);
|
||||
|
||||
/* And convert it back. */
|
||||
if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA])
|
||||
== NULL)
|
||||
{
|
||||
result = -1l;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
rwlock_unlock (elf->lock);
|
||||
return result;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS,checksum))
|
||||
@@ -0,0 +1,69 @@
|
||||
/* Return the size of an object file type.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libelf.h>
|
||||
#include "libelfP.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
size_t
|
||||
elfw2(LIBELFBITS, fsize) (Elf_Type type, size_t count, unsigned int version)
|
||||
{
|
||||
/* We do not have differences between file and memory sizes. Better
|
||||
not since otherwise `mmap' would not work. */
|
||||
if (unlikely (version == EV_NONE) || unlikely (version >= EV_NUM))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (unlikely (type >= ELF_T_NUM))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_TYPE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if EV_NUM != 2
|
||||
return (count
|
||||
* __libelf_type_sizes[version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
|
||||
#else
|
||||
return (count
|
||||
* __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
|
||||
#endif
|
||||
}
|
||||
|
||||
//#define local_strong_alias(n1, n2) strong_alias (n1, n2)
|
||||
//local_strong_alias (elfw2(LIBELFBITS, fsize), __elfw2(LIBELFBITS, msize))
|
||||
@@ -0,0 +1,83 @@
|
||||
/* Return section compression header.
|
||||
Copyright (C) 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libelf.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
ElfW2(LIBELFBITS,Chdr) *
|
||||
elfw2(LIBELFBITS,getchdr) (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = elfw2(LIBELFBITS,getshdr) (scn);
|
||||
if (shdr == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Must have SHF_COMPRESSED flag set. Allocated or no bits sections
|
||||
can never be compressed. */
|
||||
if ((shdr->sh_flags & SHF_ALLOC) != 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (shdr->sh_type == SHT_NULL
|
||||
|| shdr->sh_type == SHT_NOBITS)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOT_COMPRESSED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* This makes sure the data is in the correct format, so we don't
|
||||
need to swap fields. */
|
||||
Elf_Data *d = elf_getdata (scn, NULL);
|
||||
if (d == NULL)
|
||||
return NULL;
|
||||
|
||||
if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/* Get ELF header.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libelf.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
static ElfW2(LIBELFBITS,Ehdr) *
|
||||
getehdr_impl (Elf *elf, int wrlock)
|
||||
{
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (unlikely (elf->kind != ELF_K_ELF))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
again:
|
||||
if (elf->class == 0)
|
||||
{
|
||||
if (!wrlock)
|
||||
{
|
||||
rwlock_unlock (elf->lock);
|
||||
rwlock_wrlock (elf->lock);
|
||||
wrlock = 1;
|
||||
goto again;
|
||||
}
|
||||
elf->class = ELFW(ELFCLASS,LIBELFBITS);
|
||||
}
|
||||
else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_CLASS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Ehdr) *
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,getehdr_wrlock) (Elf *elf)
|
||||
{
|
||||
return getehdr_impl (elf, 1);
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Ehdr) *
|
||||
elfw2(LIBELFBITS,getehdr) (Elf *elf)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Ehdr) *result;
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
rwlock_rdlock (elf->lock);
|
||||
result = getehdr_impl (elf, 0);
|
||||
rwlock_unlock (elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/* Get ELF program header table.
|
||||
Copyright (C) 1998-2010, 2014, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
ElfW2(LIBELFBITS,Phdr) *
|
||||
__elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *result;
|
||||
|
||||
/* If the program header entry has already been filled in the code
|
||||
below must already have been run. So the class is set, too. No
|
||||
need to waste any more time here. */
|
||||
result = elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
if (likely (result != NULL))
|
||||
return result;
|
||||
|
||||
if (elf->class == 0)
|
||||
elf->class = ELFW(ELFCLASS,LIBELFBITS);
|
||||
else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_CLASS);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (likely (result == NULL))
|
||||
{
|
||||
/* Read the section header table. */
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
|
||||
/* If no program header exists return NULL. */
|
||||
size_t phnum;
|
||||
if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
|
||||
goto out;
|
||||
if (phnum == 0 || ehdr->e_phoff == 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NO_PHDR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Check this doesn't overflow. */
|
||||
size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
|
||||
|
||||
if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
|
||||
|| ehdr->e_phoff > elf->maximum_size
|
||||
|| elf->maximum_size - ehdr->e_phoff < size)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (elf->map_address != NULL)
|
||||
{
|
||||
/* First see whether the information in the ELF header is
|
||||
valid and it does not ask for too much. */
|
||||
if (unlikely (ehdr->e_phoff >= elf->maximum_size)
|
||||
|| unlikely (elf->maximum_size - ehdr->e_phoff < size))
|
||||
{
|
||||
/* Something is wrong. */
|
||||
__libelf_seterrno (ELF_E_INVALID_PHDR);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* All the data is already mapped. Use it. */
|
||||
void *file_phdr = ((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_phoff);
|
||||
if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
|
||||
&& (ALLOW_UNALIGNED
|
||||
|| ((uintptr_t) file_phdr
|
||||
& (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
|
||||
/* Simply use the mapped data. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
|
||||
else
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *notcvt;
|
||||
ElfW2(LIBELFBITS,Phdr) *phdr;
|
||||
|
||||
/* Allocate memory for the program headers. We know the number
|
||||
of entries from the ELF header. */
|
||||
phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
|
||||
(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
|
||||
ELF_F_MALLOCED | ELF_F_DIRTY;
|
||||
|
||||
/* Now copy the data and at the same time convert the
|
||||
byte order. */
|
||||
|
||||
if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
|
||||
{
|
||||
assert (! ALLOW_UNALIGNED);
|
||||
memcpy (phdr, file_phdr, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool copy = ! (ALLOW_UNALIGNED
|
||||
|| ((uintptr_t) file_phdr
|
||||
& (__alignof__ (ElfW2(LIBELFBITS,Phdr))
|
||||
- 1)) == 0);
|
||||
if (! copy)
|
||||
notcvt = file_phdr;
|
||||
else
|
||||
{
|
||||
notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
|
||||
if (unlikely (notcvt == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
memcpy (notcvt, file_phdr, size);
|
||||
}
|
||||
|
||||
for (size_t cnt = 0; cnt < phnum; ++cnt)
|
||||
{
|
||||
CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
|
||||
CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
|
||||
CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
|
||||
CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
|
||||
CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
|
||||
CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
|
||||
CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
|
||||
CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
|
||||
}
|
||||
|
||||
if (copy)
|
||||
free (notcvt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (likely (elf->fildes != -1))
|
||||
{
|
||||
/* Allocate memory for the program headers. We know the number
|
||||
of entries from the ELF header. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr =
|
||||
(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
|
||||
|
||||
/* Read the header. */
|
||||
ssize_t n = pread_retry (elf->fildes,
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr, size,
|
||||
elf->start_offset + ehdr->e_phoff);
|
||||
if (unlikely ((size_t) n != size))
|
||||
{
|
||||
/* Severe problems. We cannot read the data. */
|
||||
__libelf_seterrno (ELF_E_READ_ERROR);
|
||||
free (elf->state.ELFW(elf,LIBELFBITS).phdr);
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* If the byte order of the file is not the same as the one
|
||||
of the host convert the data now. */
|
||||
if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *phdr
|
||||
= elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
|
||||
for (size_t cnt = 0; cnt < phnum; ++cnt)
|
||||
{
|
||||
CONVERT (phdr[cnt].p_type);
|
||||
CONVERT (phdr[cnt].p_offset);
|
||||
CONVERT (phdr[cnt].p_vaddr);
|
||||
CONVERT (phdr[cnt].p_paddr);
|
||||
CONVERT (phdr[cnt].p_filesz);
|
||||
CONVERT (phdr[cnt].p_memsz);
|
||||
CONVERT (phdr[cnt].p_flags);
|
||||
CONVERT (phdr[cnt].p_align);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The file descriptor was already enabled and not all data was
|
||||
read. */
|
||||
__libelf_seterrno (ELF_E_FD_DISABLED);
|
||||
goto out;
|
||||
}
|
||||
|
||||
result = elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
}
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Phdr) *
|
||||
elfw2(LIBELFBITS,getphdr) (Elf *elf)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *result;
|
||||
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (unlikely (elf->kind != ELF_K_ELF))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If the program header entry has already been filled in the code
|
||||
* in getphdr_wrlock must already have been run. So the class is
|
||||
* set, too. No need to waste any more time here. */
|
||||
result = elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
if (likely (result != NULL))
|
||||
return result;
|
||||
|
||||
rwlock_wrlock (elf->lock);
|
||||
result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
|
||||
rwlock_unlock (elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS,getphdr))
|
||||
@@ -0,0 +1,299 @@
|
||||
/* Return section header.
|
||||
Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
static ElfW2(LIBELFBITS,Shdr) *
|
||||
load_shdr_wrlock (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *result;
|
||||
|
||||
/* Read the section header table. */
|
||||
Elf *elf = scn->elf;
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
|
||||
/* Try again, maybe the data is there now. */
|
||||
result = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (result != NULL)
|
||||
goto out;
|
||||
|
||||
size_t shnum;
|
||||
if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
|
||||
|| shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
|
||||
goto out;
|
||||
size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
|
||||
|
||||
/* Allocate memory for the section headers. We know the number
|
||||
of entries from the ELF header. */
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
|
||||
(ElfW2(LIBELFBITS,Shdr) *) malloc (size);
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
|
||||
|
||||
if (elf->map_address != NULL)
|
||||
{
|
||||
/* First see whether the information in the ELF header is
|
||||
valid and it does not ask for too much. */
|
||||
if (unlikely (ehdr->e_shoff >= elf->maximum_size)
|
||||
|| unlikely (elf->maximum_size - ehdr->e_shoff < size))
|
||||
{
|
||||
/* Something is wrong. */
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
|
||||
goto free_and_out;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *notcvt;
|
||||
|
||||
/* All the data is already mapped. If we could use it
|
||||
directly this would already have happened. Unless
|
||||
we allocated the memory ourselves and the ELF_F_MALLOCED
|
||||
flag is set. */
|
||||
void *file_shdr = ((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_shoff);
|
||||
|
||||
assert ((elf->flags & ELF_F_MALLOCED)
|
||||
|| ehdr->e_ident[EI_DATA] != MY_ELFDATA
|
||||
|| elf->cmd == ELF_C_READ_MMAP
|
||||
|| (! ALLOW_UNALIGNED
|
||||
&& ((uintptr_t) file_shdr
|
||||
& (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
|
||||
|
||||
/* Now copy the data and at the same time convert the byte order. */
|
||||
if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
|
||||
{
|
||||
assert ((elf->flags & ELF_F_MALLOCED)
|
||||
|| elf->cmd == ELF_C_READ_MMAP
|
||||
|| ! ALLOW_UNALIGNED);
|
||||
memcpy (shdr, file_shdr, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool copy = ! (ALLOW_UNALIGNED
|
||||
|| ((uintptr_t) file_shdr
|
||||
& (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1))
|
||||
== 0);
|
||||
if (! copy)
|
||||
notcvt = (ElfW2(LIBELFBITS,Shdr) *)
|
||||
((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_shoff);
|
||||
else
|
||||
{
|
||||
notcvt = (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
|
||||
if (unlikely (notcvt == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto out;
|
||||
}
|
||||
memcpy (notcvt, ((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_shoff),
|
||||
size);
|
||||
}
|
||||
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
|
||||
CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
|
||||
CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
|
||||
CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
|
||||
CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
|
||||
CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
|
||||
CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
|
||||
CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
|
||||
CONVERT_TO (shdr[cnt].sh_addralign,
|
||||
notcvt[cnt].sh_addralign);
|
||||
CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
|
||||
|
||||
/* If this is a section with an extended index add a
|
||||
reference in the section which uses the extended
|
||||
index. */
|
||||
if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
|
||||
&& shdr[cnt].sh_link < shnum)
|
||||
elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
|
||||
= cnt;
|
||||
|
||||
/* Set the own shndx_index field in case it has not yet
|
||||
been set. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
|
||||
elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
|
||||
= -1;
|
||||
}
|
||||
|
||||
if (copy)
|
||||
free (notcvt);
|
||||
}
|
||||
}
|
||||
else if (likely (elf->fildes != -1))
|
||||
{
|
||||
/* Read the header. */
|
||||
ssize_t n = pread_retry (elf->fildes,
|
||||
elf->state.ELFW(elf,LIBELFBITS).shdr, size,
|
||||
elf->start_offset + ehdr->e_shoff);
|
||||
if (unlikely ((size_t) n != size))
|
||||
{
|
||||
/* Severe problems. We cannot read the data. */
|
||||
__libelf_seterrno (ELF_E_READ_ERROR);
|
||||
goto free_and_out;
|
||||
}
|
||||
|
||||
/* If the byte order of the file is not the same as the one
|
||||
of the host convert the data now. */
|
||||
if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
CONVERT (shdr[cnt].sh_name);
|
||||
CONVERT (shdr[cnt].sh_type);
|
||||
CONVERT (shdr[cnt].sh_flags);
|
||||
CONVERT (shdr[cnt].sh_addr);
|
||||
CONVERT (shdr[cnt].sh_offset);
|
||||
CONVERT (shdr[cnt].sh_size);
|
||||
CONVERT (shdr[cnt].sh_link);
|
||||
CONVERT (shdr[cnt].sh_info);
|
||||
CONVERT (shdr[cnt].sh_addralign);
|
||||
CONVERT (shdr[cnt].sh_entsize);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The file descriptor was already enabled and not all data was
|
||||
read. Undo the allocation. */
|
||||
__libelf_seterrno (ELF_E_FD_DISABLED);
|
||||
|
||||
free_and_out:
|
||||
free (shdr);
|
||||
elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
|
||||
elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
|
||||
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set the pointers in the `scn's. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
|
||||
= &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
|
||||
|
||||
result = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
assert (result != NULL);
|
||||
|
||||
out:
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
scn_valid (Elf_Scn *scn)
|
||||
{
|
||||
if (scn == NULL)
|
||||
return false;
|
||||
|
||||
if (unlikely (scn->elf->state.elf.ehdr == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_CLASS);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *result;
|
||||
|
||||
if (!scn_valid (scn))
|
||||
return NULL;
|
||||
|
||||
result = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (result == NULL)
|
||||
{
|
||||
rwlock_unlock (scn->elf->lock);
|
||||
rwlock_wrlock (scn->elf->lock);
|
||||
result = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (result == NULL)
|
||||
result = load_shdr_wrlock (scn);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *result;
|
||||
|
||||
if (!scn_valid (scn))
|
||||
return NULL;
|
||||
|
||||
result = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (result == NULL)
|
||||
result = load_shdr_wrlock (scn);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *
|
||||
elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Shdr) *result;
|
||||
|
||||
if (!scn_valid (scn))
|
||||
return NULL;
|
||||
|
||||
rwlock_rdlock (scn->elf->lock);
|
||||
result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
|
||||
rwlock_unlock (scn->elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* Create new ELF header.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
ElfW2(LIBELFBITS,Ehdr) *
|
||||
elfw2(LIBELFBITS,newehdr) (Elf *elf)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Ehdr) *result;
|
||||
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (unlikely (elf->kind != ELF_K_ELF))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rwlock_wrlock (elf->lock);
|
||||
|
||||
if (elf->class == 0)
|
||||
elf->class = ELFW(ELFCLASS,LIBELFBITS);
|
||||
else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_CLASS);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Don't create an ELF header if one already exists. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL)
|
||||
{
|
||||
/* We use the memory in the ELF descriptor. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr =
|
||||
&elf->state.ELFW(elf,LIBELFBITS).ehdr_mem;
|
||||
|
||||
/* We clear this memory. */
|
||||
memset (elf->state.ELFW(elf,LIBELFBITS).ehdr, '\0',
|
||||
sizeof (ElfW2(LIBELFBITS,Ehdr)));
|
||||
|
||||
/* Mark the ELF header has modified. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
result = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
|
||||
out:
|
||||
rwlock_unlock (elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS,newehdr))
|
||||
@@ -0,0 +1,190 @@
|
||||
/* Create new ELF program header table.
|
||||
Copyright (C) 1999-2010, 2014, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
ElfW2(LIBELFBITS,Phdr) *
|
||||
elfw2(LIBELFBITS,newphdr) (Elf *elf, size_t count)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *result;
|
||||
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (unlikely (elf->kind != ELF_K_ELF))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_OPERAND);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rwlock_wrlock (elf->lock);
|
||||
|
||||
if (elf->class == 0)
|
||||
elf->class = ELFW(ELFCLASS,LIBELFBITS);
|
||||
else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_CLASS);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* A COUNT of zero means remove existing table. */
|
||||
if (count == 0)
|
||||
{
|
||||
/* Free the old program header. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
|
||||
{
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
|
||||
free (elf->state.ELFW(elf,LIBELFBITS).phdr);
|
||||
|
||||
/* Set the pointer to NULL. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
|
||||
/* Set the `e_phnum' member to the new value. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
|
||||
/* Also clear any old PN_XNUM extended value. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0)
|
||||
elf->state.ELFW(elf,LIBELFBITS).scns.data[0]
|
||||
.shdr.ELFW(e,LIBELFBITS)->sh_info = 0;
|
||||
/* Also set the size. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
|
||||
sizeof (ElfW2(LIBELFBITS,Phdr));
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
|
||||
elf->flags |= ELF_F_DIRTY;
|
||||
__libelf_seterrno (ELF_E_NOERROR);
|
||||
}
|
||||
|
||||
result = NULL;
|
||||
}
|
||||
else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
|
||||
|| count == PN_XNUM
|
||||
|| elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
|
||||
{
|
||||
if (unlikely (count > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_INDEX);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
|
||||
if (unlikely (count >= PN_XNUM && scn0->shdr.ELFW(e,LIBELFBITS) == NULL))
|
||||
{
|
||||
/* Something is wrong with section zero, but we need it to write
|
||||
the extended phdr count. */
|
||||
__libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
|
||||
result = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Allocate a new program header with the appropriate number of
|
||||
elements. */
|
||||
result = (ElfW2(LIBELFBITS,Phdr) *)
|
||||
realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
|
||||
count * sizeof (ElfW2(LIBELFBITS,Phdr)));
|
||||
if (result == NULL)
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
else
|
||||
{
|
||||
/* Now set the result. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr = result;
|
||||
if (count >= PN_XNUM)
|
||||
{
|
||||
/* We have to write COUNT into the zeroth section's sh_info. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt == 0)
|
||||
{
|
||||
assert (elf->state.ELFW(elf,LIBELFBITS).scns.max > 0);
|
||||
elf->state.ELFW(elf,LIBELFBITS).scns.cnt = 1;
|
||||
}
|
||||
scn0->shdr.ELFW(e,LIBELFBITS)->sh_info = count;
|
||||
scn0->shdr_flags |= ELF_F_DIRTY;
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = PN_XNUM;
|
||||
}
|
||||
else
|
||||
/* Set the `e_phnum' member to the new value. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
|
||||
/* Clear the whole memory. */
|
||||
memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
|
||||
/* Also set the size. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
|
||||
elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
|
||||
/* Remember we allocated the array and mark the structure is
|
||||
modified. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
|
||||
ELF_F_DIRTY | ELF_F_MALLOCED;
|
||||
/* We have to rewrite the entire file if the size of the
|
||||
program header is changed. */
|
||||
elf->flags |= ELF_F_DIRTY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have the same number of entries. Just clear the array. */
|
||||
assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
|
||||
== elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
|
||||
|
||||
/* Mark the structure as modified. */
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
|
||||
|
||||
result = elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
|
||||
}
|
||||
|
||||
out:
|
||||
rwlock_unlock (elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS,newphdr))
|
||||
@@ -0,0 +1,99 @@
|
||||
/* Get section at specific index.
|
||||
Copyright (C) 2005, 2008, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
Elf_Scn *
|
||||
elfw2(LIBELFBITS,offscn) (Elf *elf, ElfW2(LIBELFBITS,Off) offset)
|
||||
{
|
||||
if (elf == NULL)
|
||||
return NULL;
|
||||
|
||||
if (unlikely (elf->kind != ELF_K_ELF))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_HANDLE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Elf_ScnList *runp = &elf->state.ELFW(elf,LIBELFBITS).scns;
|
||||
|
||||
/* If we have not looked at section headers before,
|
||||
we might need to read them in first. */
|
||||
if (runp->cnt > 0
|
||||
&& unlikely (runp->data[0].shdr.ELFW(e,LIBELFBITS) == NULL)
|
||||
&& unlikely (elfw2(LIBELFBITS,getshdr) (&runp->data[0]) == NULL))
|
||||
return NULL;
|
||||
|
||||
rwlock_rdlock (elf->lock);
|
||||
|
||||
Elf_Scn *result = NULL;
|
||||
|
||||
/* Find the section in the list. */
|
||||
while (1)
|
||||
{
|
||||
for (unsigned int i = 0; i < runp->cnt; ++i)
|
||||
if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_offset == offset)
|
||||
{
|
||||
result = &runp->data[i];
|
||||
|
||||
/* If this section is empty, the following one has the same
|
||||
sh_offset. We presume the caller is looking for a nonempty
|
||||
section, so keep looking if this one is empty. */
|
||||
if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_size != 0
|
||||
&& runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_type != SHT_NOBITS)
|
||||
goto out;
|
||||
}
|
||||
|
||||
runp = runp->next;
|
||||
if (runp == NULL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_OFFSET);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
rwlock_unlock (elf->lock);
|
||||
|
||||
return result;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS,offscn))
|
||||
@@ -0,0 +1,850 @@
|
||||
/* Write changed data structures.
|
||||
Copyright (C) 2000-2010, 2014, 2015, 2016 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <libelf.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
static int
|
||||
compare_sections (const void *a, const void *b)
|
||||
{
|
||||
const Elf_Scn **scna = (const Elf_Scn **) a;
|
||||
const Elf_Scn **scnb = (const Elf_Scn **) b;
|
||||
|
||||
if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
|
||||
< (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
|
||||
return -1;
|
||||
|
||||
if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
|
||||
> (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
|
||||
return 1;
|
||||
|
||||
if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
|
||||
< (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
|
||||
return -1;
|
||||
|
||||
if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
|
||||
> (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
|
||||
return 1;
|
||||
|
||||
if ((*scna)->index < (*scnb)->index)
|
||||
return -1;
|
||||
|
||||
if ((*scna)->index > (*scnb)->index)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Insert the sections in the list into the provided array and sort
|
||||
them according to their start offsets. For sections with equal
|
||||
start offsets, the size is used; for sections with equal start
|
||||
offsets and sizes, the section index is used. Sorting by size
|
||||
ensures that zero-length sections are processed first, which
|
||||
is what we want since they do not advance our file writing position. */
|
||||
static void
|
||||
sort_sections (Elf_Scn **scns, Elf_ScnList *list)
|
||||
{
|
||||
Elf_Scn **scnp = scns;
|
||||
do
|
||||
for (size_t cnt = 0; cnt < list->cnt; ++cnt)
|
||||
*scnp++ = &list->data[cnt];
|
||||
while ((list = list->next) != NULL);
|
||||
|
||||
qsort (scns, scnp - scns, sizeof (*scns), compare_sections);
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
fill_mmap (size_t offset, char *last_position, char *scn_start,
|
||||
char *const shdr_start, char *const shdr_end)
|
||||
{
|
||||
size_t written = 0;
|
||||
|
||||
if (last_position < shdr_start)
|
||||
{
|
||||
written = MIN (scn_start + offset - last_position,
|
||||
shdr_start - last_position);
|
||||
|
||||
memset (last_position, __libelf_fill_byte, written);
|
||||
}
|
||||
|
||||
if (last_position + written != scn_start + offset
|
||||
&& shdr_end < scn_start + offset)
|
||||
{
|
||||
char *fill_start = MAX (shdr_end, scn_start);
|
||||
memset (fill_start, __libelf_fill_byte,
|
||||
scn_start + offset - fill_start);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
bool previous_scn_changed = false;
|
||||
|
||||
/* We need the ELF header several times. */
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
|
||||
/* Write out the ELF header. */
|
||||
if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
/* If the type sizes should be different at some time we have to
|
||||
rewrite this code. */
|
||||
assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
|
||||
== elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
|
||||
}
|
||||
else if (elf->map_address + elf->start_offset != ehdr)
|
||||
memcpy (elf->map_address + elf->start_offset, ehdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Ehdr)));
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* We start writing sections after the ELF header only if there is
|
||||
no program header. */
|
||||
previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
|
||||
}
|
||||
|
||||
size_t phnum;
|
||||
if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
|
||||
return -1;
|
||||
|
||||
/* Write out the program header table. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
|
||||
&& ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
|
||||
& ELF_F_DIRTY))
|
||||
{
|
||||
/* If the type sizes should be different at some time we have to
|
||||
rewrite this code. */
|
||||
assert (sizeof (ElfW2(LIBELFBITS,Phdr))
|
||||
== elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
|
||||
|
||||
/* Maybe the user wants a gap between the ELF header and the program
|
||||
header. */
|
||||
if (ehdr->e_phoff > ehdr->e_ehsize)
|
||||
memset (elf->map_address + elf->start_offset + ehdr->e_ehsize,
|
||||
__libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize);
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
|
||||
}
|
||||
else
|
||||
memcpy (elf->map_address + elf->start_offset + ehdr->e_phoff,
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* We modified the program header. Maybe this created a gap so
|
||||
we have to write fill bytes, if necessary. */
|
||||
previous_scn_changed = true;
|
||||
}
|
||||
|
||||
/* From now on we have to keep track of the last position to eventually
|
||||
fill the gaps with the prescribed fill byte. */
|
||||
char *last_position = ((char *) elf->map_address + elf->start_offset
|
||||
+ MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
|
||||
ehdr->e_phoff)
|
||||
+ elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
|
||||
|
||||
/* Write all the sections. Well, only those which are modified. */
|
||||
if (shnum > 0)
|
||||
{
|
||||
if (unlikely (shnum > SIZE_MAX / sizeof (Elf_Scn *)))
|
||||
return 1;
|
||||
|
||||
Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
|
||||
Elf_Scn **scns = (Elf_Scn **) malloc (shnum * sizeof (Elf_Scn *));
|
||||
if (unlikely (scns == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return -1;
|
||||
}
|
||||
char *const shdr_start = ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff);
|
||||
char *const shdr_end = shdr_start + ehdr->e_shnum * ehdr->e_shentsize;
|
||||
|
||||
#if EV_NUM != 2
|
||||
xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
|
||||
#else
|
||||
# undef shdr_fctp
|
||||
# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
|
||||
#endif
|
||||
#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
|
||||
|
||||
/* Get all sections into the array and sort them. */
|
||||
sort_sections (scns, list);
|
||||
|
||||
/* We possibly have to copy the section header data because moving
|
||||
the sections might overwrite the data. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
|
||||
if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
|
||||
&& (scn->shdr_flags & ELF_F_MALLOCED) == 0
|
||||
&& scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
|
||||
{
|
||||
assert ((char *) elf->map_address + elf->start_offset
|
||||
< (char *) scn->shdr.ELFW(e,LIBELFBITS));
|
||||
assert ((char *) scn->shdr.ELFW(e,LIBELFBITS)
|
||||
< ((char *) elf->map_address + elf->start_offset
|
||||
+ elf->maximum_size));
|
||||
|
||||
void *p = malloc (sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
if (unlikely (p == NULL))
|
||||
{
|
||||
free (scns);
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return -1;
|
||||
}
|
||||
scn->shdr.ELFW(e,LIBELFBITS)
|
||||
= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
}
|
||||
|
||||
/* If the file is mmaped and the original position of the
|
||||
section in the file is lower than the new position we
|
||||
need to save the section content since otherwise it is
|
||||
overwritten before it can be copied. If there are
|
||||
multiple data segments in the list only the first can be
|
||||
from the file. */
|
||||
if (((char *) elf->map_address + elf->start_offset
|
||||
<= (char *) scn->data_list.data.d.d_buf)
|
||||
&& ((char *) scn->data_list.data.d.d_buf
|
||||
< ((char *) elf->map_address + elf->start_offset
|
||||
+ elf->maximum_size))
|
||||
&& (((char *) elf->map_address + elf->start_offset
|
||||
+ scn->shdr.ELFW(e,LIBELFBITS)->sh_offset)
|
||||
> (char *) scn->data_list.data.d.d_buf))
|
||||
{
|
||||
void *p = malloc (scn->data_list.data.d.d_size);
|
||||
if (unlikely (p == NULL))
|
||||
{
|
||||
free (scns);
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return -1;
|
||||
}
|
||||
scn->data_list.data.d.d_buf = scn->data_base
|
||||
= memcpy (p, scn->data_list.data.d.d_buf,
|
||||
scn->data_list.data.d.d_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate over all the section in the order in which they
|
||||
appear in the output file. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
if (scn->index == 0)
|
||||
{
|
||||
/* The dummy section header entry. It should not be
|
||||
possible to mark this "section" as dirty. */
|
||||
assert ((scn->flags & ELF_F_DIRTY) == 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (shdr->sh_type == SHT_NOBITS)
|
||||
goto next;
|
||||
|
||||
char *scn_start = ((char *) elf->map_address
|
||||
+ elf->start_offset + shdr->sh_offset);
|
||||
Elf_Data_List *dl = &scn->data_list;
|
||||
bool scn_changed = false;
|
||||
|
||||
if (scn->data_list_rear != NULL)
|
||||
do
|
||||
{
|
||||
assert (dl->data.d.d_off >= 0);
|
||||
assert ((GElf_Off) dl->data.d.d_off <= shdr->sh_size);
|
||||
assert (dl->data.d.d_size <= (shdr->sh_size
|
||||
- (GElf_Off) dl->data.d.d_off));
|
||||
|
||||
/* If there is a gap, fill it. */
|
||||
if (scn_start + dl->data.d.d_off > last_position
|
||||
&& (dl->data.d.d_off == 0
|
||||
|| ((scn->flags | dl->flags | elf->flags)
|
||||
& ELF_F_DIRTY) != 0))
|
||||
{
|
||||
fill_mmap (dl->data.d.d_off, last_position, scn_start,
|
||||
shdr_start, shdr_end);
|
||||
}
|
||||
|
||||
last_position = scn_start + dl->data.d.d_off;
|
||||
|
||||
if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
/* Let it go backward if the sections use a bogus
|
||||
layout with overlaps. We'll overwrite the stupid
|
||||
user's section data with the latest one, rather than
|
||||
crashing. */
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) (last_position, dl->data.d.d_buf,
|
||||
dl->data.d.d_size, 1);
|
||||
|
||||
last_position += dl->data.d.d_size;
|
||||
}
|
||||
else if (dl->data.d.d_size != 0)
|
||||
last_position = mempcpy (last_position,
|
||||
dl->data.d.d_buf,
|
||||
dl->data.d.d_size);
|
||||
|
||||
scn_changed = true;
|
||||
}
|
||||
else
|
||||
last_position += dl->data.d.d_size;
|
||||
|
||||
assert (scn_start + dl->data.d.d_off + dl->data.d.d_size
|
||||
== last_position);
|
||||
|
||||
dl->flags &= ~ELF_F_DIRTY;
|
||||
|
||||
dl = dl->next;
|
||||
}
|
||||
while (dl != NULL);
|
||||
else
|
||||
{
|
||||
/* If the previous section (or the ELF/program
|
||||
header) changed we might have to fill the gap. */
|
||||
if (scn_start > last_position && previous_scn_changed)
|
||||
fill_mmap (0, last_position, scn_start,
|
||||
shdr_start, shdr_end);
|
||||
|
||||
/* We have to trust the existing section header information. */
|
||||
last_position = scn_start + shdr->sh_size;
|
||||
}
|
||||
|
||||
|
||||
previous_scn_changed = scn_changed;
|
||||
next:
|
||||
scn->flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* Fill the gap between last section and section header table if
|
||||
necessary. */
|
||||
if ((elf->flags & ELF_F_DIRTY)
|
||||
&& last_position < ((char *) elf->map_address + elf->start_offset
|
||||
+ ehdr->e_shoff))
|
||||
memset (last_position, __libelf_fill_byte,
|
||||
(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
|
||||
- last_position);
|
||||
|
||||
/* Write the section header table entry if necessary. */
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
|
||||
if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
if (unlikely (change_bo))
|
||||
(*shdr_fctp) (&shdr_dest[scn->index],
|
||||
scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
|
||||
else
|
||||
memcpy (&shdr_dest[scn->index],
|
||||
scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
|
||||
/* If we previously made a copy of the section header
|
||||
entry we now have to adjust the pointer again so
|
||||
point to new place in the mapping. */
|
||||
if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
|
||||
&& (scn->shdr_flags & ELF_F_MALLOCED) == 0
|
||||
&& scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
|
||||
{
|
||||
free (scn->shdr.ELFW(e,LIBELFBITS));
|
||||
scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index];
|
||||
}
|
||||
|
||||
scn->shdr_flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
}
|
||||
free (scns);
|
||||
}
|
||||
|
||||
/* That was the last part. Clear the overall flag. */
|
||||
elf->flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* Make sure the content hits the disk. */
|
||||
char *msync_start = ((char *) elf->map_address
|
||||
+ (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1)));
|
||||
char *msync_end = ((char *) elf->map_address
|
||||
+ elf->start_offset + ehdr->e_shoff
|
||||
+ ehdr->e_shentsize * shnum);
|
||||
(void) msync (msync_start, msync_end - msync_start, MS_SYNC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Size of the buffer we use to generate the blocks of fill bytes. */
|
||||
#define FILLBUFSIZE 4096
|
||||
|
||||
/* If we have to convert the section buffer contents we have to use
|
||||
temporary buffer. Only buffers up to MAX_TMPBUF bytes are allocated
|
||||
on the stack. */
|
||||
#define MAX_TMPBUF 32768
|
||||
|
||||
|
||||
/* Helper function to write out fill bytes. */
|
||||
static int
|
||||
fill (int fd, off_t pos, size_t len, char *fillbuf, size_t *filledp)
|
||||
{
|
||||
size_t filled = *filledp;
|
||||
size_t fill_len = MIN (len, FILLBUFSIZE);
|
||||
|
||||
if (unlikely (fill_len > filled) && filled < FILLBUFSIZE)
|
||||
{
|
||||
/* Initialize a few more bytes. */
|
||||
memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled);
|
||||
*filledp = filled = fill_len;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* This many bytes we want to write in this round. */
|
||||
size_t n = MIN (filled, len);
|
||||
|
||||
if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
pos += n;
|
||||
len -= n;
|
||||
}
|
||||
while (len > 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
|
||||
{
|
||||
char fillbuf[FILLBUFSIZE];
|
||||
size_t filled = 0;
|
||||
bool previous_scn_changed = false;
|
||||
|
||||
/* We need the ELF header several times. */
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
|
||||
|
||||
/* Write out the ELF header. */
|
||||
if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Ehdr) tmp_ehdr;
|
||||
ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr;
|
||||
|
||||
/* If the type sizes should be different at some time we have to
|
||||
rewrite this code. */
|
||||
assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
|
||||
== elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
|
||||
#endif
|
||||
|
||||
/* Write the converted ELF header in a temporary buffer. */
|
||||
(*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
|
||||
|
||||
/* This is the buffer we want to write. */
|
||||
out_ehdr = &tmp_ehdr;
|
||||
}
|
||||
|
||||
/* Write out the ELF header. */
|
||||
if (unlikely (pwrite_retry (elf->fildes, out_ehdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
|
||||
!= sizeof (ElfW2(LIBELFBITS,Ehdr))))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* We start writing sections after the ELF header only if there is
|
||||
no program header. */
|
||||
previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
|
||||
}
|
||||
|
||||
/* If the type sizes should be different at some time we have to
|
||||
rewrite this code. */
|
||||
assert (sizeof (ElfW2(LIBELFBITS,Phdr))
|
||||
== elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
|
||||
|
||||
size_t phnum;
|
||||
if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
|
||||
return -1;
|
||||
|
||||
/* Write out the program header table. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
|
||||
&& ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
|
||||
& ELF_F_DIRTY))
|
||||
{
|
||||
ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL;
|
||||
ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
|
||||
|
||||
/* Maybe the user wants a gap between the ELF header and the program
|
||||
header. */
|
||||
if (ehdr->e_phoff > ehdr->e_ehsize
|
||||
&& unlikely (fill (elf->fildes, ehdr->e_ehsize,
|
||||
ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled)
|
||||
!= 0))
|
||||
return 1;
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
/* Today there is only one version of the ELF header. */
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
|
||||
#endif
|
||||
|
||||
/* Allocate sufficient memory. */
|
||||
tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
|
||||
malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
|
||||
if (unlikely (tmp_phdr == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Write the converted ELF header in a temporary buffer. */
|
||||
(*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr,
|
||||
sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
|
||||
|
||||
/* This is the buffer we want to write. */
|
||||
out_phdr = tmp_phdr;
|
||||
}
|
||||
|
||||
/* Write out the ELF header. */
|
||||
size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum;
|
||||
if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr,
|
||||
phdr_size, ehdr->e_phoff)
|
||||
!= phdr_size))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* This is a no-op we we have not allocated any memory. */
|
||||
free (tmp_phdr);
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
|
||||
|
||||
/* We modified the program header. Maybe this created a gap so
|
||||
we have to write fill bytes, if necessary. */
|
||||
previous_scn_changed = true;
|
||||
}
|
||||
|
||||
/* From now on we have to keep track of the last position to eventually
|
||||
fill the gaps with the prescribed fill byte. */
|
||||
off_t last_offset;
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
|
||||
last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
|
||||
else
|
||||
last_offset = (ehdr->e_phoff + sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
|
||||
|
||||
/* Write all the sections. Well, only those which are modified. */
|
||||
if (shnum > 0)
|
||||
{
|
||||
if (unlikely (shnum > SIZE_MAX / (sizeof (Elf_Scn *)
|
||||
+ sizeof (ElfW2(LIBELFBITS,Shdr)))))
|
||||
return 1;
|
||||
|
||||
off_t shdr_offset = elf->start_offset + ehdr->e_shoff;
|
||||
#if EV_NUM != 2
|
||||
xfct_t shdr_fctp = __elf_xfctstom[__libelf_version - 1][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR];
|
||||
#else
|
||||
# undef shdr_fctp
|
||||
# define shdr_fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
|
||||
#endif
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr_data;
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr_data_mem = NULL;
|
||||
if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
|
||||
|| (elf->flags & ELF_F_DIRTY))
|
||||
{
|
||||
shdr_data_mem = (ElfW2(LIBELFBITS,Shdr) *)
|
||||
malloc (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
if (unlikely (shdr_data_mem == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return -1;
|
||||
}
|
||||
shdr_data = shdr_data_mem;
|
||||
}
|
||||
else
|
||||
shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr;
|
||||
int shdr_flags = elf->flags;
|
||||
|
||||
/* Get all sections into the array and sort them. */
|
||||
Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
|
||||
Elf_Scn **scns = (Elf_Scn **) malloc (shnum * sizeof (Elf_Scn *));
|
||||
if (unlikely (scns == NULL))
|
||||
{
|
||||
free (shdr_data_mem);
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
return -1;
|
||||
}
|
||||
sort_sections (scns, list);
|
||||
|
||||
for (size_t cnt = 0; cnt < shnum; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = scns[cnt];
|
||||
if (scn->index == 0)
|
||||
{
|
||||
/* The dummy section header entry. It should not be
|
||||
possible to mark this "section" as dirty. */
|
||||
assert ((scn->flags & ELF_F_DIRTY) == 0);
|
||||
goto next;
|
||||
}
|
||||
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
if (shdr->sh_type == SHT_NOBITS)
|
||||
goto next;
|
||||
|
||||
off_t scn_start = elf->start_offset + shdr->sh_offset;
|
||||
Elf_Data_List *dl = &scn->data_list;
|
||||
bool scn_changed = false;
|
||||
|
||||
if (scn->data_list_rear != NULL)
|
||||
do
|
||||
{
|
||||
/* If there is a gap, fill it. */
|
||||
if (scn_start + dl->data.d.d_off > last_offset
|
||||
&& ((previous_scn_changed && dl->data.d.d_off == 0)
|
||||
|| ((scn->flags | dl->flags | elf->flags)
|
||||
& ELF_F_DIRTY) != 0))
|
||||
{
|
||||
if (unlikely (fill (elf->fildes, last_offset,
|
||||
(scn_start + dl->data.d.d_off)
|
||||
- last_offset, fillbuf,
|
||||
&filled) != 0))
|
||||
{
|
||||
fail_free:
|
||||
free (shdr_data_mem);
|
||||
free (scns);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
last_offset = scn_start + dl->data.d.d_off;
|
||||
|
||||
if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
|
||||
{
|
||||
char tmpbuf[MAX_TMPBUF];
|
||||
void *buf = dl->data.d.d_buf;
|
||||
|
||||
/* Let it go backward if the sections use a bogus
|
||||
layout with overlaps. We'll overwrite the stupid
|
||||
user's section data with the latest one, rather than
|
||||
crashing. */
|
||||
|
||||
if (unlikely (change_bo))
|
||||
{
|
||||
#if EV_NUM != 2
|
||||
xfct_t fctp;
|
||||
fctp = __elf_xfctstom[__libelf_version - 1][dl->data.d.d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type];
|
||||
#else
|
||||
# undef fctp
|
||||
# define fctp __elf_xfctstom[0][EV_CURRENT - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
|
||||
#endif
|
||||
|
||||
buf = tmpbuf;
|
||||
if (dl->data.d.d_size > MAX_TMPBUF)
|
||||
{
|
||||
buf = malloc (dl->data.d.d_size);
|
||||
if (unlikely (buf == NULL))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_NOMEM);
|
||||
goto fail_free;
|
||||
}
|
||||
}
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
|
||||
}
|
||||
|
||||
ssize_t n = pwrite_retry (elf->fildes, buf,
|
||||
dl->data.d.d_size,
|
||||
last_offset);
|
||||
if (unlikely ((size_t) n != dl->data.d.d_size))
|
||||
{
|
||||
if (buf != dl->data.d.d_buf && buf != tmpbuf)
|
||||
free (buf);
|
||||
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
if (buf != dl->data.d.d_buf && buf != tmpbuf)
|
||||
free (buf);
|
||||
|
||||
scn_changed = true;
|
||||
}
|
||||
|
||||
last_offset += dl->data.d.d_size;
|
||||
|
||||
dl->flags &= ~ELF_F_DIRTY;
|
||||
|
||||
dl = dl->next;
|
||||
}
|
||||
while (dl != NULL);
|
||||
else
|
||||
{
|
||||
/* If the previous section (or the ELF/program
|
||||
header) changed we might have to fill the gap. */
|
||||
if (scn_start > last_offset && previous_scn_changed)
|
||||
{
|
||||
if (unlikely (fill (elf->fildes, last_offset,
|
||||
scn_start - last_offset, fillbuf,
|
||||
&filled) != 0))
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
last_offset = scn_start + shdr->sh_size;
|
||||
}
|
||||
|
||||
previous_scn_changed = scn_changed;
|
||||
next:
|
||||
/* Collect the section header table information. */
|
||||
if (unlikely (change_bo))
|
||||
(*shdr_fctp) (&shdr_data[scn->index],
|
||||
scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
|
||||
else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
|
||||
|| (elf->flags & ELF_F_DIRTY))
|
||||
memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr)));
|
||||
|
||||
shdr_flags |= scn->shdr_flags;
|
||||
scn->shdr_flags &= ~ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* Fill the gap between last section and section header table if
|
||||
necessary. */
|
||||
if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset
|
||||
&& unlikely (fill (elf->fildes, last_offset,
|
||||
shdr_offset - last_offset,
|
||||
fillbuf, &filled) != 0))
|
||||
goto fail_free;
|
||||
|
||||
/* Write out the section header table. */
|
||||
if (shdr_flags & ELF_F_DIRTY
|
||||
&& unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data,
|
||||
sizeof (ElfW2(LIBELFBITS,Shdr))
|
||||
* shnum, shdr_offset)
|
||||
!= sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_WRITE_ERROR);
|
||||
goto fail_free;
|
||||
}
|
||||
|
||||
free (shdr_data_mem);
|
||||
free (scns);
|
||||
}
|
||||
|
||||
/* That was the last part. Clear the overall flag. */
|
||||
elf->flags &= ~ELF_F_DIRTY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,443 @@
|
||||
/* Update data structures for changes.
|
||||
Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2000.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <libelf.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <system.h>
|
||||
#include "libelfP.h"
|
||||
#include "elf-knowledge.h"
|
||||
#include "portable_endian.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static int
|
||||
ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
|
||||
size_t shnum, int *change_bop)
|
||||
{
|
||||
/* Always write the magic bytes. */
|
||||
if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
|
||||
{
|
||||
memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* Always set the file class. */
|
||||
update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
|
||||
|
||||
/* Set the data encoding if necessary. */
|
||||
if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
|
||||
{
|
||||
ehdr->e_ident[EI_DATA] =
|
||||
BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_DATA_ENCODING);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
*change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
|
||||
&& ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
|
||||
|| (BYTE_ORDER == BIG_ENDIAN
|
||||
&& ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
|
||||
|
||||
/* Unconditionally overwrite the ELF version. */
|
||||
update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
|
||||
|
||||
if (unlikely (ehdr->e_version == EV_NONE))
|
||||
{
|
||||
ehdr->e_version = EV_CURRENT;
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
else if (unlikely (ehdr->e_version >= EV_NUM))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (unlikely (shnum >= SHN_LORESERVE))
|
||||
{
|
||||
update_if_changed (ehdr->e_shnum, 0,
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
|
||||
}
|
||||
else
|
||||
update_if_changed (ehdr->e_shnum, shnum,
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
|
||||
|
||||
if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
|
||||
{
|
||||
ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
/* If phnum is zero make sure e_phoff is also zero and not some random
|
||||
value. That would cause trouble in update_file. */
|
||||
if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
|
||||
{
|
||||
ehdr->e_phoff = 0;
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
off_t
|
||||
internal_function
|
||||
__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
|
||||
{
|
||||
ElfW2(LIBELFBITS,Ehdr) *ehdr;
|
||||
int changed = 0;
|
||||
int ehdr_flags = 0;
|
||||
|
||||
ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
|
||||
|
||||
/* Set the default values. */
|
||||
if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
|
||||
return -1;
|
||||
|
||||
/* At least the ELF header is there. */
|
||||
off_t size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
|
||||
|
||||
/* Set the program header position. */
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
|
||||
(void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
|
||||
if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
|
||||
{
|
||||
size_t phnum;
|
||||
if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
|
||||
return -1;
|
||||
|
||||
if (elf->flags & ELF_F_LAYOUT)
|
||||
{
|
||||
/* The user is supposed to fill out e_phoff. Use it and
|
||||
e_phnum to determine the maximum extend. */
|
||||
size = MAX ((size_t) size,
|
||||
ehdr->e_phoff
|
||||
+ elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
|
||||
}
|
||||
else
|
||||
{
|
||||
update_if_changed (ehdr->e_phoff,
|
||||
elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
|
||||
ehdr_flags);
|
||||
|
||||
/* We need no alignment here. */
|
||||
size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
|
||||
}
|
||||
}
|
||||
|
||||
if (shnum > 0)
|
||||
{
|
||||
struct Elf_Scn *scn1 = NULL;
|
||||
Elf_ScnList *list;
|
||||
bool first = true;
|
||||
|
||||
assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
|
||||
|
||||
if (shnum >= SHN_LORESERVE)
|
||||
{
|
||||
/* We have to fill in the number of sections in the header
|
||||
of the zeroth section. */
|
||||
Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
|
||||
|
||||
update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
|
||||
shnum, scn0->shdr_flags);
|
||||
}
|
||||
|
||||
/* Go over all sections and find out how large they are. */
|
||||
list = &elf->state.ELFW(elf,LIBELFBITS).scns;
|
||||
|
||||
/* Find the first section. */
|
||||
if (list->cnt > 1)
|
||||
scn1 = &list->data[1];
|
||||
else if (list->next != NULL)
|
||||
scn1 = &list->next->data[0];
|
||||
|
||||
/* Load the section headers if necessary. This loads the
|
||||
headers for all sections. */
|
||||
if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL)
|
||||
(void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1);
|
||||
|
||||
do
|
||||
{
|
||||
for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
|
||||
{
|
||||
Elf_Scn *scn = &list->data[cnt];
|
||||
ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
|
||||
off_t offset = 0;
|
||||
|
||||
assert (shdr != NULL);
|
||||
ElfW2(LIBELFBITS,Word) sh_entsize = shdr->sh_entsize;
|
||||
ElfW2(LIBELFBITS,Word) sh_align = shdr->sh_addralign ?: 1;
|
||||
if (unlikely (! powerof2 (sh_align)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_ALIGN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Set the sh_entsize value if we can reliably detect it. */
|
||||
switch (shdr->sh_type)
|
||||
{
|
||||
case SHT_SYMTAB:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
|
||||
break;
|
||||
case SHT_RELA:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
|
||||
break;
|
||||
case SHT_GROUP:
|
||||
/* Only relocatable files can contain section groups. */
|
||||
if (ehdr->e_type != ET_REL)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_GROUP_NOT_REL);
|
||||
return -1;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
case SHT_SYMTAB_SHNDX:
|
||||
sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
|
||||
break;
|
||||
case SHT_HASH:
|
||||
sh_entsize = SH_ENTSIZE_HASH (ehdr);
|
||||
break;
|
||||
case SHT_DYNAMIC:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
|
||||
break;
|
||||
case SHT_REL:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
|
||||
break;
|
||||
case SHT_DYNSYM:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
|
||||
break;
|
||||
case SHT_SUNW_move:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
|
||||
break;
|
||||
case SHT_SUNW_syminfo:
|
||||
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the section header contained the wrong entry size
|
||||
correct it and mark the header as modified. */
|
||||
update_if_changed (shdr->sh_entsize, sh_entsize,
|
||||
scn->shdr_flags);
|
||||
|
||||
if (scn->data_read == 0
|
||||
&& __libelf_set_rawdata_wrlock (scn) != 0)
|
||||
/* Something went wrong. The error value is already set. */
|
||||
return -1;
|
||||
|
||||
/* Iterate over all data blocks. */
|
||||
if (list->data[cnt].data_list_rear != NULL)
|
||||
{
|
||||
Elf_Data_List *dl = &scn->data_list;
|
||||
|
||||
while (dl != NULL)
|
||||
{
|
||||
Elf_Data *data = &dl->data.d;
|
||||
if (dl == &scn->data_list && data->d_buf == NULL
|
||||
&& scn->rawdata.d.d_buf != NULL)
|
||||
data = &scn->rawdata.d;
|
||||
|
||||
if (unlikely (data->d_version == EV_NONE)
|
||||
|| unlikely (data->d_version >= EV_NUM))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_UNKNOWN_VERSION);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlikely (! powerof2 (data->d_align)))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_ALIGN);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sh_align = MAX (sh_align, data->d_align);
|
||||
|
||||
if (elf->flags & ELF_F_LAYOUT)
|
||||
{
|
||||
/* The user specified the offset and the size.
|
||||
All we have to do is check whether this block
|
||||
fits in the size specified for the section. */
|
||||
if (unlikely ((GElf_Word) (data->d_off
|
||||
+ data->d_size)
|
||||
> shdr->sh_size))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Determine the padding. */
|
||||
offset = ((offset + data->d_align - 1)
|
||||
& ~(data->d_align - 1));
|
||||
|
||||
update_if_changed (data->d_off, offset, changed);
|
||||
|
||||
offset += data->d_size;
|
||||
}
|
||||
|
||||
/* Next data block. */
|
||||
dl = dl->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* Get the size of the section from the raw data. If
|
||||
none is available the value is zero. */
|
||||
offset += scn->rawdata.d.d_size;
|
||||
|
||||
if (elf->flags & ELF_F_LAYOUT)
|
||||
{
|
||||
size = MAX ((GElf_Word) size,
|
||||
(shdr->sh_type != SHT_NOBITS
|
||||
? shdr->sh_offset + shdr->sh_size : 0));
|
||||
|
||||
/* The alignment must be a power of two. This is a
|
||||
requirement from the ELF specification. Additionally
|
||||
we test for the alignment of the section being large
|
||||
enough for the largest alignment required by a data
|
||||
block. */
|
||||
if (unlikely (! powerof2 (shdr->sh_addralign))
|
||||
|| unlikely ((shdr->sh_addralign ?: 1) < sh_align))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_ALIGN);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* How much alignment do we need for this section. */
|
||||
update_if_changed (shdr->sh_addralign, sh_align,
|
||||
scn->shdr_flags);
|
||||
|
||||
size = (size + sh_align - 1) & ~(sh_align - 1);
|
||||
int offset_changed = 0;
|
||||
update_if_changed (shdr->sh_offset, (GElf_Word) size,
|
||||
offset_changed);
|
||||
changed |= offset_changed;
|
||||
|
||||
if (offset_changed && scn->data_list_rear == NULL)
|
||||
{
|
||||
/* The position of the section in the file
|
||||
changed. Create the section data list. */
|
||||
if (__elf_getdata_rdlock (scn, NULL) == NULL)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* See whether the section size is correct. */
|
||||
update_if_changed (shdr->sh_size, (GElf_Word) offset,
|
||||
changed);
|
||||
|
||||
if (shdr->sh_type != SHT_NOBITS)
|
||||
size += offset;
|
||||
|
||||
scn->flags |= changed;
|
||||
}
|
||||
|
||||
/* Check that the section size is actually a multiple of
|
||||
the entry size. */
|
||||
if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
|
||||
&& (elf->flags & ELF_F_PERMISSIVE) == 0)
|
||||
{
|
||||
/* For compressed sections check the uncompressed size. */
|
||||
ElfW2(LIBELFBITS,Word) sh_size;
|
||||
if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
|
||||
sh_size = shdr->sh_size;
|
||||
else
|
||||
{
|
||||
ElfW2(LIBELFBITS,Chdr) *chdr;
|
||||
chdr = elfw2(LIBELFBITS,getchdr) (scn);
|
||||
if (unlikely (chdr == NULL))
|
||||
return -1;
|
||||
sh_size = chdr->ch_size;
|
||||
}
|
||||
|
||||
if (unlikely (sh_size % shdr->sh_entsize != 0))
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (list->next == NULL || list->cnt == list->max);
|
||||
|
||||
first = false;
|
||||
}
|
||||
while ((list = list->next) != NULL);
|
||||
|
||||
/* Store section information. */
|
||||
update_if_changed (ehdr->e_shentsize,
|
||||
elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
|
||||
if (elf->flags & ELF_F_LAYOUT)
|
||||
{
|
||||
/* The user is supposed to fill out e_shoff. Use it and
|
||||
e_shnum (or sh_size of the dummy, first section header)
|
||||
to determine the maximum extend. */
|
||||
size = MAX ((GElf_Word) size,
|
||||
(ehdr->e_shoff
|
||||
+ (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Align for section header table.
|
||||
|
||||
Yes, we use `sizeof' and not `__alignof__' since we do not
|
||||
want to be surprised by architectures with less strict
|
||||
alignment rules. */
|
||||
#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
|
||||
size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
|
||||
|
||||
update_if_changed (ehdr->e_shoff, (GElf_Word) size, elf->flags);
|
||||
|
||||
/* Account for the section header size. */
|
||||
size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
|
||||
}
|
||||
}
|
||||
|
||||
elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
|
||||
|
||||
return size;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/* Convert from memory to file representation.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
#include "portable_endian.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
Elf_Data *
|
||||
elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
|
||||
unsigned int encode)
|
||||
{
|
||||
/* First test whether the input data is really suitable for this
|
||||
type. This means, whether there is an integer number of records.
|
||||
Note that for this implementation the memory and file size of the
|
||||
data types are identical. */
|
||||
#if EV_NUM != 2
|
||||
size_t recsize = __libelf_type_sizes[src->d_version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
|
||||
#else
|
||||
size_t recsize = __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
|
||||
#endif
|
||||
|
||||
if (src->d_size % recsize != 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Next see whether the converted data fits in the output buffer. */
|
||||
if (src->d_size > dest->d_size)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_DEST_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Test the encode parameter. */
|
||||
if (encode != ELFDATA2LSB && encode != ELFDATA2MSB)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Determine the translation function to use.
|
||||
|
||||
At this point we make an assumption which is valid for all
|
||||
existing implementations so far: the memory and file sizes are
|
||||
the same. This has very important consequences:
|
||||
a) The requirement that the source and destination buffer can
|
||||
overlap can easily be fulfilled.
|
||||
b) We need only one function to convert from and memory to file
|
||||
and vice versa since the function only has to copy and/or
|
||||
change the byte order.
|
||||
*/
|
||||
if ((__BYTE_ORDER == __LITTLE_ENDIAN && encode == ELFDATA2LSB)
|
||||
|| (__BYTE_ORDER == __BIG_ENDIAN && encode == ELFDATA2MSB))
|
||||
{
|
||||
/* We simply have to copy since the byte order is the same. */
|
||||
if (src->d_buf != dest->d_buf)
|
||||
memmove (dest->d_buf, src->d_buf, src->d_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
xfct_t fctp;
|
||||
|
||||
/* Get a pointer to the transformation functions. The `#ifdef' is
|
||||
a small optimization since we don't anticipate another ELF
|
||||
version and so would waste "precious" code. */
|
||||
#if EV_NUM != 2
|
||||
fctp = __elf_xfctstom[dest->d_version - 1][src->d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
|
||||
#else
|
||||
fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) (dest->d_buf, src->d_buf, src->d_size, 1);
|
||||
}
|
||||
|
||||
/* Now set the real destination type and length since the operation was
|
||||
successful. */
|
||||
dest->d_type = src->d_type;
|
||||
dest->d_size = src->d_size;
|
||||
|
||||
return dest;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS, xlatetof))
|
||||
@@ -0,0 +1,126 @@
|
||||
/* Convert from file to memory representation.
|
||||
Copyright (C) 1998, 1999, 2000, 2002, 2012, 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "libelfP.h"
|
||||
#include "portable_endian.h"
|
||||
|
||||
#ifndef LIBELFBITS
|
||||
# define LIBELFBITS 32
|
||||
#endif
|
||||
|
||||
|
||||
Elf_Data *
|
||||
elfw2(LIBELFBITS, xlatetom) (Elf_Data *dest, const Elf_Data *src,
|
||||
unsigned int encode)
|
||||
{
|
||||
/* First test whether the input data is really suitable for this
|
||||
type. This means, whether there is an integer number of records.
|
||||
Note that for this implementation the memory and file size of the
|
||||
data types are identical. */
|
||||
#if EV_NUM != 2
|
||||
size_t recsize = __libelf_type_sizes[src->d_version - 1][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
|
||||
#else
|
||||
size_t recsize = __libelf_type_sizes[0][ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
|
||||
#endif
|
||||
|
||||
|
||||
/* We shouldn't require integer number of records when processing
|
||||
notes. Payload bytes follow the header immediately, it's not an
|
||||
array of records as is the case otherwise. */
|
||||
if (src->d_type != ELF_T_NHDR
|
||||
&& src->d_size % recsize != 0)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_DATA);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Next see whether the converted data fits in the output buffer. */
|
||||
if (src->d_size > dest->d_size)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_DEST_SIZE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Test the encode parameter. */
|
||||
if (encode != ELFDATA2LSB && encode != ELFDATA2MSB)
|
||||
{
|
||||
__libelf_seterrno (ELF_E_INVALID_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Determine the translation function to use.
|
||||
|
||||
At this point we make an assumption which is valid for all
|
||||
existing implementations so far: the memory and file sizes are
|
||||
the same. This has very important consequences:
|
||||
a) The requirement that the source and destination buffer can
|
||||
overlap can easily be fulfilled.
|
||||
b) We need only one function to convert from and memory to file
|
||||
and vice versa since the function only has to copy and/or
|
||||
change the byte order.
|
||||
*/
|
||||
if ((BYTE_ORDER == LITTLE_ENDIAN && encode == ELFDATA2LSB)
|
||||
|| (BYTE_ORDER == BIG_ENDIAN && encode == ELFDATA2MSB))
|
||||
{
|
||||
/* We simply have to copy since the byte order is the same. */
|
||||
if (src->d_buf != dest->d_buf)
|
||||
memmove (dest->d_buf, src->d_buf, src->d_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
xfct_t fctp;
|
||||
|
||||
/* Get a pointer to the transformation functions. The `#ifdef' is
|
||||
a small optimization since we don't anticipate another ELF
|
||||
version and so would waste "precious" code. */
|
||||
#if EV_NUM != 2
|
||||
fctp = __elf_xfctstom[src->d_version - 1][dest->d_version - 1][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
|
||||
#else
|
||||
fctp = __elf_xfctstom[0][0][ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
|
||||
#endif
|
||||
|
||||
/* Do the real work. */
|
||||
(*fctp) (dest->d_buf, src->d_buf, src->d_size, 0);
|
||||
}
|
||||
|
||||
/* Now set the real destination type and length since the operation was
|
||||
successful. */
|
||||
dest->d_type = src->d_type;
|
||||
dest->d_size = src->d_size;
|
||||
|
||||
return dest;
|
||||
}
|
||||
INTDEF(elfw2(LIBELFBITS, xlatetom))
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Compute simple checksum from permanent parts of the ELF file.
|
||||
Copyright (C) 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_checksum.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Return the size of an object file type.
|
||||
Copyright (C) 1998, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_fsize.c"
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Return section compression header.
|
||||
Copyright (C) 2015 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_getchdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Return program header table.
|
||||
Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_getehdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Return program header table.
|
||||
Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_getphdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Return section header.
|
||||
Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_getshdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Create new program header table.
|
||||
Copyright (C) 1999, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1999.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_newehdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Create new program header table.
|
||||
Copyright (C) 1999, 2002 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 1999.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_newphdr.c"
|
||||
@@ -0,0 +1,31 @@
|
||||
/* Return program header table.
|
||||
Copyright (C) 2005 Red Hat, Inc.
|
||||
This file is part of elfutils.
|
||||
Written by Ulrich Drepper <drepper@redhat.com>, 2005.
|
||||
|
||||
This file is free software; you can redistribute it and/or modify
|
||||
it under the terms of either
|
||||
|
||||
* the GNU Lesser General Public License as published by the Free
|
||||
Software Foundation; either version 3 of the License, or (at
|
||||
your option) any later version
|
||||
|
||||
or
|
||||
|
||||
* 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
|
||||
|
||||
or both in parallel, as here.
|
||||
|
||||
elfutils 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 copies of the GNU General Public License and
|
||||
the GNU Lesser General Public License along with this program. If
|
||||
not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define LIBELFBITS 64
|
||||
#include "elf32_offscn.c"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user