Merge pull request #27 from autc04/segments

Segments: Multiple-segment Apps for 68K. UnloadSeg is still missing.
This commit is contained in:
Wolfgang Thaller
2017-09-30 23:41:47 +02:00
committed by GitHub
212 changed files with 24406 additions and 15959 deletions
-3
View File
@@ -1,6 +1,3 @@
CIncludes*
RIncludes*
Universal Headers*
*~
.*.swp
CMakeLists.txt.user
+4 -2
View File
@@ -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()
+3
View File
@@ -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)
+6 -4
View File
@@ -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;
+91 -8
View File
@@ -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;
}
+34
View File
@@ -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)
+202
View File
@@ -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;
}
+27
View File
@@ -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
+302
View File
@@ -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;
}
+387
View File
@@ -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, &sectionHeaderStringTableIdx);
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();
}
+61
View File
@@ -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
+69
View File
@@ -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();
}
+60
View File
@@ -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
+237
View File
@@ -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;
}
}
}
+75
View File
@@ -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
+64
View File
@@ -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 "";
}
+55
View File
@@ -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
+45
View File
@@ -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);
}
}
+48
View File
@@ -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
+81
View File
@@ -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;
}
+51
View File
@@ -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
+1
View File
@@ -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
+80 -16
View File
@@ -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;
+1 -1
View File
@@ -19,7 +19,7 @@ public:
basilisk,
applesingle,
underscore_appledouble,
//appledouble
percent_appledouble
};
ResourceFile();
+8
View File
@@ -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
View File
@@ -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"
)
+36 -9
View File
@@ -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
View File
@@ -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;
}
+17
View File
@@ -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
View File
@@ -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
+8 -6
View File
@@ -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}
-24
View File
@@ -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
-22
View File
@@ -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
View File
@@ -1 +0,0 @@
elf2flt
-1
View File
@@ -1 +0,0 @@
:pserver:anonymous@cvs.uclinux.org:/var/cvs
-114
View File
@@ -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
-62
View File
@@ -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).
-198
View File
@@ -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);
}
-44
View File
@@ -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
-1418
View File
File diff suppressed because it is too large Load Diff
-1577
View File
File diff suppressed because it is too large Load Diff
-5508
View File
File diff suppressed because it is too large Load Diff
-235
View File
@@ -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)
-2171
View File
File diff suppressed because it is too large Load Diff
-161
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
-215
View File
@@ -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
View File
@@ -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
*/
-380
View File
@@ -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);
}
/****************************************************************************/
-251
View File
@@ -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
-580
View File
@@ -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;
}
-241
View File
@@ -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
View File
@@ -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;
}
-75
View File
@@ -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);
+9
View File
@@ -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"
+10
View File
@@ -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 ""
+4 -1
View File
@@ -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
+1 -3
View File
@@ -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)
+1
View File
@@ -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.
+4
View File
@@ -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
;;
+7
View File
@@ -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
View File
@@ -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>.
+19 -20
View File
@@ -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.
+165
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+95
View File
@@ -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.
+24
View File
@@ -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.
+6
View File
@@ -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
File diff suppressed because it is too large Load Diff
+342
View File
@@ -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 */
+515
View File
@@ -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 */
+330
View File
@@ -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)
+33
View File
@@ -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);
}
+162
View File
@@ -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 */
+195
View File
@@ -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 */
+102
View File
@@ -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;
}
+75
View File
@@ -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 */
+80
View File
@@ -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 */
+168
View File
@@ -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))
+69
View File
@@ -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))
+83
View File
@@ -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;
}
+96
View File
@@ -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;
}
+265
View File
@@ -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))
+299
View File
@@ -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;
}
+91
View File
@@ -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))
+190
View File
@@ -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))
+99
View File
@@ -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))
+850
View File
@@ -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;
}
+443
View File
@@ -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;
}
+121
View File
@@ -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))
+126
View File
@@ -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))
+31
View File
@@ -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"
+31
View File
@@ -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"
+30
View File
@@ -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"
+31
View File
@@ -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"
+31
View File
@@ -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"
+31
View File
@@ -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"
+31
View File
@@ -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"
+31
View File
@@ -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"
+31
View File
@@ -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