Skip to content

Commit

Permalink
Support the '.note.android.ident' section
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Feb 28, 2018
1 parent 3cf0ec9 commit d13db18
Show file tree
Hide file tree
Showing 30 changed files with 559 additions and 99 deletions.
8 changes: 7 additions & 1 deletion api/python/ELF/CMakeLists.txt
@@ -1,6 +1,5 @@
set(LIEF_PYTHON_ELF_SRC
"${CMAKE_CURRENT_LIST_DIR}/pyELF.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyNote.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyDynamicEntry.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersionAuxRequirement.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pySymbolVersion.cpp"
Expand All @@ -27,6 +26,13 @@ set(LIEF_PYTHON_ELF_SRC
"${CMAKE_CURRENT_LIST_DIR}/pySizes.cpp"
)

set(LIEF_PYTHON_ELF_NOTE
"${CMAKE_CURRENT_LIST_DIR}/objects/pyNote.cpp"
"${CMAKE_CURRENT_LIST_DIR}/objects/pyAndroidNote.cpp"
)

list(APPEND LIEF_PYTHON_ELF_SRC ${LIEF_PYTHON_ELF_NOTE})

set(LIEF_PYTHON_ELF_HDR
"${CMAKE_CURRENT_LIST_DIR}/pyELF.hpp")

Expand Down
67 changes: 67 additions & 0 deletions api/python/ELF/objects/pyAndroidNote.cpp
@@ -0,0 +1,67 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <string>
#include <sstream>

#include "pyELF.hpp"

#include "LIEF/visitors/Hash.hpp"
#include "LIEF/ELF/AndroidNote.hpp"

template<class T>
using getter_t = T (AndroidNote::*)(void) const;

template<class T>
using setter_t = void (AndroidNote::*)(T);

void init_ELF_AndroidNote_class(py::module& m) {

py::class_<AndroidNote, Note>(m, "AndroidNote")

.def_property("sdk_version",
static_cast<getter_t<uint32_t>>(&AndroidNote::sdk_version),
static_cast<setter_t<uint32_t>>(&AndroidNote::sdk_version),
"Target SDK platform"
)

.def_property("ndk_version",
static_cast<getter_t<std::string>>(&AndroidNote::ndk_version),
static_cast<setter_t<const std::string&>>(&AndroidNote::ndk_version),
"Android NDK version used to build the current binary"
)

.def_property("ndk_build_number",
static_cast<getter_t<std::string>>(&AndroidNote::ndk_build_number),
static_cast<setter_t<const std::string&>>(&AndroidNote::ndk_build_number),
"Android NDK build number"
)

.def("__eq__", &AndroidNote::operator==)
.def("__ne__", &AndroidNote::operator!=)
.def("__hash__",
[] (const AndroidNote& note) {
return LIEF::Hash::hash(note);
})

.def("__str__",
[] (const AndroidNote& note)
{
std::ostringstream stream;
stream << note;
std::string str = stream.str();
return str;
});
}
6 changes: 3 additions & 3 deletions api/python/ELF/objects/pyNote.cpp
Expand Up @@ -50,8 +50,8 @@ void init_ELF_Note_class(py::module& m) {
)

.def_property("description",
static_cast<getter_t<const std::vector<uint8_t>&>>(&Note::description),
static_cast<setter_t<const std::vector<uint8_t>&>>(&Note::description),
static_cast<getter_t<const Note::description_t&>>(&Note::description),
static_cast<setter_t<const Note::description_t&>>(&Note::description),
"Return the description associated with the note"
)

Expand All @@ -61,7 +61,7 @@ void init_ELF_Note_class(py::module& m) {
)

.def_property_readonly("version",
static_cast<getter_t<std::tuple<uint32_t, uint32_t, uint32_t>>>(&Note::version),
static_cast<getter_t<Note::version_t>>(&Note::version),
"Return the target version as ``(Major, Minor, Patch)``. Require a :attr:`~lief.ELF.NOTE_TYPES.ABI_TAG` :attr:`~lief.ELF.Note.type`"
)

Expand Down
1 change: 1 addition & 0 deletions api/python/ELF/pyELF.cpp
Expand Up @@ -47,6 +47,7 @@ void init_ELF_module(py::module& m) {
init_ELF_SysvHash_class(LIEF_ELF_module);
init_ELF_Builder_class(LIEF_ELF_module);
init_ELF_Note_class(LIEF_ELF_module);
init_ELF_AndroidNote_class(LIEF_ELF_module);

py::module LIEF_ELF32_module = LIEF_ELF_module.def_submodule("ELF32", "");
init_ELF32_sizes(LIEF_ELF32_module);
Expand Down
1 change: 1 addition & 0 deletions api/python/ELF/pyELF.hpp
Expand Up @@ -46,6 +46,7 @@ void init_ELF_GnuHash_class(py::module&);
void init_ELF_SysvHash_class(py::module&);
void init_ELF_Builder_class(py::module&);
void init_ELF_Note_class(py::module&);
void init_ELF_AndroidNote_class(py::module&);

// Enums
void init_ELF_Structures_enum(py::module&);
Expand Down
2 changes: 2 additions & 0 deletions api/python/ELF/pyELFStructures.cpp
Expand Up @@ -862,6 +862,7 @@ void init_ELF_Structures_enum(py::module& m) {


py::enum_<NOTE_TYPES>(m, "NOTE_TYPES")
.value(PY_ENUM(NOTE_TYPES::NT_UNKNOWN))
.value(PY_ENUM(NOTE_TYPES::NT_GNU_ABI_TAG))
.value(PY_ENUM(NOTE_TYPES::NT_GNU_HWCAP))
.value(PY_ENUM(NOTE_TYPES::NT_GNU_BUILD_ID))
Expand All @@ -870,6 +871,7 @@ void init_ELF_Structures_enum(py::module& m) {


py::enum_<NOTE_ABIS>(m, "NOTE_ABIS")
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_UNKNOWN))
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_LINUX))
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_GNU))
.value(PY_ENUM(NOTE_ABIS::ELF_NOTE_OS_SOLARIS2))
Expand Down
8 changes: 8 additions & 0 deletions doc/sphinx/api/cpp/elf.rst
Expand Up @@ -156,6 +156,14 @@ Note

----------

Android Note
************

.. doxygenclass:: LIEF::ELF::AndroidNote
:project: lief

----------


Utilities
*********
Expand Down
10 changes: 10 additions & 0 deletions doc/sphinx/api/python/elf.rst
Expand Up @@ -203,6 +203,16 @@ Note

----------

Android Note
*************

.. autoclass:: lief.ELF.AndroidNote
:members:
:inherited-members:
:undoc-members:

----------


Builder
*******
Expand Down
Empty file modified examples/python/abstract_reader.py 100755 → 100644
Empty file.
11 changes: 7 additions & 4 deletions examples/python/elf_reader.py 100755 → 100644
Expand Up @@ -385,14 +385,17 @@ def print_notes(binary):
print(format_str.format("Description:", description_str))

if ELF.NOTE_TYPES(note.type) == ELF.NOTE_TYPES.ABI_TAG:
try:
version = note.version

if type(note) == lief.ELF.AndroidNote:
print(format_dec.format("SDK Version:", note.sdk_version))
print(format_str.format("NDK Version:", note.ndk_version))
print(format_str.format("NDK build number:", note.ndk_build_number))
else:
version = note.version
version_str = "{:d}.{:d}.{:d}".format(version[0], version[1], version[2])

print(format_str.format("ABI:", note.abi))
print(format_str.format("Version:", version_str))
except lief.corrupted:
pass

if ELF.NOTE_TYPES(note.type) == ELF.NOTE_TYPES.GOLD_VERSION:
print(format_str.format("Version:", "".join(map(chr, note.description))))
Expand Down
Empty file modified examples/python/macho_reader.py 100755 → 100644
Empty file.
Empty file modified examples/python/pe_reader.py 100755 → 100644
Empty file.
1 change: 1 addition & 0 deletions include/LIEF/ELF.hpp
Expand Up @@ -23,6 +23,7 @@
#include "LIEF/ELF/utils.hpp"
#include "LIEF/ELF/Segment.hpp"
#include "LIEF/ELF/Builder.hpp"
#include "LIEF/ELF/AndroidNote.hpp"
#include "LIEF/ELF/EnumToString.hpp"

#endif
77 changes: 77 additions & 0 deletions include/LIEF/ELF/AndroidNote.hpp
@@ -0,0 +1,77 @@
/* Copyright 2017 R. Thomas
* Copyright 2017 Quarkslab
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef LIEF_ELF_ANDROID_NOTE_H_
#define LIEF_ELF_ANDROID_NOTE_H_

#include <vector>
#include <iostream>

#include "LIEF/Visitable.hpp"
#include "LIEF/visibility.h"
#include "LIEF/ELF/Note.hpp"

namespace LIEF {
namespace ELF {

class Parser;
class Builder;
class Binary;

//! Class representing the ".note.android.ident" section
//!
//! @See: https://android.googlesource.com/platform/ndk/+/ndk-release-r16/sources/crt/crtbrand.S#39
class DLL_PUBLIC AndroidNote : public Note {

friend class Parser;
friend class Builder;
friend class Binary;
public:
static constexpr const char NAME[] = "Android";

public:
using Note::Note;


//! Target SDK version
uint32_t sdk_version(void) const;

//! NDK version used
std::string ndk_version(void) const;

//! NDK build number
std::string ndk_build_number(void) const;

void sdk_version(uint32_t version);
void ndk_version(const std::string& ndk_version);
void ndk_build_number(const std::string& ndk_build_number);

bool operator==(const AndroidNote& rhs) const;
bool operator!=(const AndroidNote& rhs) const;

virtual void dump(std::ostream& os) const override;

virtual void accept(Visitor& visitor) const override;

virtual ~AndroidNote(void);

DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const AndroidNote& note);
};


} // namepsace ELF
} // namespace LIEF

#endif
2 changes: 1 addition & 1 deletion include/LIEF/ELF/Builder.hpp
Expand Up @@ -103,7 +103,7 @@ class DLL_PUBLIC Builder {
template<typename ELF_T>
void build_notes(void);

void build(NOTE_TYPES type, const std::string& section_name);
void build(NOTE_TYPES type);

size_t note_offset(const Note& note);

Expand Down
35 changes: 26 additions & 9 deletions include/LIEF/ELF/Note.hpp
Expand Up @@ -35,10 +35,23 @@ class DLL_PUBLIC Note : public Visitable {
friend class Builder;
friend class Binary;

public:

//! Container used to handle the description data
using description_t = std::vector<uint8_t>;

//! Type of version
using version_t = std::array<uint32_t, 3>;

public:

//! Default value if the version is unknown
static constexpr version_t UNKNOWN_VERSION = {{0, 0, 0}};

public:
Note(void);
Note(const std::string& name, uint32_t type, const std::vector<uint8_t>& description);
Note(const std::string& name, NOTE_TYPES type, const std::vector<uint8_t>& description);
Note(const std::string& name, uint32_t type, const description_t& description);
Note(const std::string& name, NOTE_TYPES type, const description_t& description);
Note& operator=(const Note& copy);
Note(const Note& copy);
virtual ~Note(void);
Expand All @@ -50,32 +63,36 @@ class DLL_PUBLIC Note : public Visitable {
uint32_t type(void) const;

//! @brief Return the description associated with the note
const std::vector<uint8_t>& description(void) const;
const description_t& description(void) const;

description_t& description(void);

//! @brief Return the target ABI. Require a NT_GNU_ABI_TAG type
NOTE_ABIS abi(void) const;

//! @brief Return the target version as ``<Major, Minor, Patch>``. Require a NT_GNU_ABI_TAG type
std::tuple<uint32_t, uint32_t, uint32_t> version(void) const;
version_t version(void) const;

void name(const std::string& name);
void type(uint32_t type);
void description(const std::vector<uint8_t>& description);
void description(const description_t& description);

//! @brief Sizeof the **raw** note
uint64_t size(void) const;

virtual void dump(std::ostream& os) const;

bool operator==(const Note& rhs) const;
bool operator!=(const Note& rhs) const;

virtual void accept(Visitor& visitor) const override;

DLL_PUBLIC friend std::ostream& operator<<(std::ostream& os, const Note& note);

private:
std::string name_;
uint32_t type_;
std::vector<uint8_t> description_;
protected:
std::string name_;
uint32_t type_;
description_t description_;
};


Expand Down
2 changes: 2 additions & 0 deletions include/LIEF/ELF/enums.inc
Expand Up @@ -960,6 +960,7 @@ enum DYNSYM_COUNT_METHODS {
};

enum NOTE_TYPES {
NT_UNKNOWN = 0,
NT_GNU_ABI_TAG = 1,
NT_GNU_HWCAP = 2,
NT_GNU_BUILD_ID = 3,
Expand All @@ -968,6 +969,7 @@ enum NOTE_TYPES {


enum NOTE_ABIS {
ELF_NOTE_UNKNOWN = -1u,
ELF_NOTE_OS_LINUX = 0,
ELF_NOTE_OS_GNU = 1,
ELF_NOTE_OS_SOLARIS2 = 2,
Expand Down
2 changes: 1 addition & 1 deletion include/LIEF/ELF/type_traits.hpp
Expand Up @@ -92,7 +92,7 @@ using symbols_version_aux_requirement_t = std::vector<SymbolVersionAuxReq
using it_symbols_version_aux_requirement = ref_iterator<symbols_version_aux_requirement_t&>;
using it_const_symbols_version_aux_requirement = const_ref_iterator<const symbols_version_aux_requirement_t&>;

using notes_t = std::vector<Note>;
using notes_t = std::vector<Note*>;
using it_notes = ref_iterator<notes_t&>;
using it_const_notes = const_ref_iterator<const notes_t&>;

Expand Down

0 comments on commit d13db18

Please sign in to comment.