Skip to content

Commit

Permalink
Multiple changes:
Browse files Browse the repository at this point in the history
 - Fixed a buildscript bug that broke compiler flags for baron
 - Added fake class, method and field lookups to the example JNI module
 - Covnerted over to the new CX::va_list_t wrapper type for variadic c functions
 - Added modifier deserializers for JClass, JMethodID and JFieldID, closes #1
 - Added conditional logging for class, method and field fabrication. Only prints if BARON_DEBUG is set
  • Loading branch information
Matthewacon committed Nov 9, 2019
1 parent 137c488 commit 4049b27
Show file tree
Hide file tree
Showing 13 changed files with 126 additions and 16 deletions.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ if(${BUILD_BARON_DEBUG})
-O0\
-fno-inline\
-fno-omit-frame-pointer\
-DBARON_DEBUG
-DBARON_DEBUG\
")
else()
set(BUILD_FAKE_JNI_DEBUG OFF CACHE BOOL "")
Expand All @@ -28,6 +28,9 @@ endif()
set(BUILD_FAKE_JNI_TESTS OFF CACHE BOOL "")
set(BUILD_FAKE_JNI_EXAMPLES OFF CACHE BOOL "")

set(CMAKE_CXX_FLAGS ${compiler_flags})
set(CMAKE_C_FLAGS ${compiler_flags})

add_subdirectory(fake-jni)

file(GLOB_RECURSE BARON_SRC "src/**.cpp")
Expand Down
5 changes: 5 additions & 0 deletions example/jni/src/jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
JNIEXPORT
jint JNI_OnLoad(JavaVM * vm, void *) {
printf("JNI_OnLoad!\n");
JNIEnv *env;
vm->GetEnv((void **)&env, JNI_VERSION_1_8);
auto clazz = env->FindClass("yo_this is not a valid class name_");
auto mid = env->GetMethodID(clazz, "exampleMethod", "()V");
auto fid = env->GetFieldID(clazz, "someField", "I");
return JNI_VERSION_1_8;
}

Expand Down
2 changes: 2 additions & 0 deletions example/probe/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ int main(int argc, char **argv) {

vm.removeLibrary("./libjni.so");

vm.destroy();

return 0;
}
1 change: 1 addition & 0 deletions include/baron/baron.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
#include "baron/impl/interface/jvmti.h"
#include "baron/impl/env/jni.h"
#include "baron/impl/env/jvmti.h"
#include "baron/util/util.h"

namespace Baron {}
3 changes: 2 additions & 1 deletion include/baron/impl/interface/native.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <fake-jni/jvm.h>
#include <cx/vararg.h>

#include "baron/impl/jvm.h"

Expand All @@ -13,7 +14,7 @@ namespace Baron::Interface {

//inpl/interface/native/object.cpp
jobject allocObject(jclass) const override;
jobject newObjectV(jclass, jmethodID, va_list) const override;
jobject newObjectV(jclass, jmethodID, CX::va_list_t&) const override;
jobject newObjectA(jclass, jmethodID, const jvalue *) const override;
jclass getObjectClass(jobject) const override;
jboolean isInstanceOf(jobject, jclass) const override;
Expand Down
2 changes: 1 addition & 1 deletion include/baron/impl/jvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace Baron {

//FakeJni::Jvm overrides
virtual const FakeJni::JClass * findClass(const char * name) const override;
virtual void destroy() override;
virtual jint destroy() override;

//baron specific
virtual bool isClassBlacklisted(const char * name);
Expand Down
9 changes: 9 additions & 0 deletions include/baron/util/util.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <string>

namespace Baron {
std::string deserializeClassModifiers(uint32_t modifiers);
std::string deserializeFieldModifiers(uint32_t modifiers);
std::string deserializeMethodModifiers(uint32_t modifiers);
}
28 changes: 22 additions & 6 deletions src/impl/interface/native/field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,35 @@

#ifdef BARON_DEBUG
#define LOG_BLACKLIST_MATCH \
fprintf(
vm.getLog(),
"BARON INFO: Ignored blacklisted field lookup '%s#%s::%s'!\n",
className,
name,
sig
fprintf(\
vm.getLog(),\
"BARON INFO: Ignored blacklisted field lookup '%s#%s::%s'!\n",\
className,\
name,\
sig\
);
#else
#define LOG_BLACKLIST_MATCH
#endif
#ifdef BARON_DEBUG
#define LOG_FABRICATED_FIELD \
fprintf(\
vm.getLog(),\
"BARON INFO: Fabricated field %s::%s -> 0x%lx\n",\
name,\
sig,\
(intptr_t)fid\
);
#else
#define LOG_FABRICATED_FIELD
#endif
#define CHECK_BLACKLIST \
JClass * clazz = *jclazz;\
const auto className = clazz->getName();\
if (vm.isClassBlacklisted(className) || vm.isFieldBlacklisted(name, sig, className)) {\
LOG_BLACKLIST_MATCH\
return nullptr;\
}
Expand All @@ -41,6 +55,7 @@ namespace Baron::Interface {
fid = new JFieldID(fabricatedGetCallback, fabricatedSetCallback, name, sig, JFieldID::PUBLIC);
JClass * clazz = *jclazz;
clazz->registerField(fid);
LOG_FABRICATED_FIELD
}
return fid;
}
Expand All @@ -54,6 +69,7 @@ namespace Baron::Interface {
fid = new JFieldID(fabricatedGetCallback, fabricatedSetCallback, name, sig, JFieldID::PUBLIC | JFieldID::STATIC);
JClass * clazz = *jclazz;
clazz->registerField(fid);
LOG_FABRICATED_FIELD
}
return fid;
}
Expand Down
9 changes: 9 additions & 0 deletions src/impl/interface/native/method.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ fprintf(\
#define LOG_BLACKLIST_MATCH
#endif
#ifdef BARON_DEBUG
#define LOG_FABRICATED_METHOD \
fprintf(vm.getLog(), "BARON INFO: Fabricated method '%s%s' -> 0x%lx\n", name, sig, (intptr_t)mid);
#else
#define LOG_FABRICATED_CLASS
#endif
#define CHECK_BLACKLIST \
JClass * clazz = *jclazz;\
const auto className = clazz->getName();\
Expand Down Expand Up @@ -42,6 +49,7 @@ namespace Baron::Interface {
mid = new JMethodID(fabricatedMethodCallback, sig, name, JMethodID::PUBLIC);
JClass * clazz = *jclazz;
clazz->registerMethod(mid);
LOG_FABRICATED_METHOD
}
return mid;
}
Expand All @@ -55,6 +63,7 @@ namespace Baron::Interface {
mid = new JMethodID(fabricatedMethodCallback, sig, name, JMethodID::PUBLIC | JMethodID::STATIC);
JClass * clazz = *jclazz;
clazz->registerMethod(mid);
LOG_FABRICATED_METHOD
}
return mid;
}
Expand Down
2 changes: 1 addition & 1 deletion src/impl/interface/native/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Baron::Interface {
return vm.fabricateInstance(jclazz);
}

jobject NativeInterface::newObjectV(jclass jclazz, jmethodID jmid, va_list list) const {
jobject NativeInterface::newObjectV(jclass jclazz, jmethodID jmid, CX::va_list_t& list) const {
using namespace FakeJni;
auto mid = (JMethodID *)jmid;
if (mid->isArbitrary) {
Expand Down
18 changes: 13 additions & 5 deletions src/impl/jvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "baron/impl/interface/jvmti.h"
#include "baron/impl/env/jni.h"
#include "baron/impl/env/jvmti.h"
#include "baron/util/util.h"

#include <algorithm>

Expand Down Expand Up @@ -33,49 +34,56 @@ namespace Baron {
auto& ref = const_cast<Jvm &>(*this);
//Ignore class lookups for blacklisted classes
if (std::find(blacklistedClasses.begin(), blacklistedClasses.end(), name) != blacklistedClasses.end()) {
#ifdef BARON_DEBUG
fprintf(getLog(), "BARON INFO: Ignored lookup request for blacklisted class '%s'\n", name);
#endif
return nullptr;
}
auto clazz = FakeJni::Jvm::findClass(name);
if (!clazz) {
clazz = new JClass(name);
ref.registerClass(clazz);
#ifdef BARON_DEBUG
fprintf(getLog(), "BARON INFO: Fabricated class '%s' -> 0x%lx\n", name, (intptr_t)clazz);
#endif
}
return clazz;
}

//TODO print more information
// - field and function access / invocation counts
// - field and function access locations (with stack traces once libunwind is integrated)
// - serialize field and function modifiers to their respective names and print them as a list
void Jvm::destroy() {
jint Jvm::destroy() {
auto & classes = getClasses();
const auto & log = getLog();
if (classes.size() > 0) {
fprintf(log, "BARON INFO: The following classes were registered during execution:\n");
for (auto clazz : getClasses()) {
fprintf(log, "\t'%s':\n", clazz->getName());
fprintf(log, "\t - Modifiers: 0x%x\n", clazz->modifiers);
auto mods = clazz->modifiers;
fprintf(log, "\t - Modifiers: 0x%x [%s]\n", mods, deserializeClassModifiers(mods).c_str());
fprintf(log, "\t - Parent: '%s'\n", clazz->parent.getName());
fprintf(log, "\t - Fabricated: %s\n", (clazz->isArbitrary ? "yes" : "no"));
auto & fields = clazz->getFields();
fprintf(log, "\t - Fields: %u\n", fields.size());
for (auto & field : fields) {
fprintf(log, "\t\t'%s' -> '%s':\n", field->getName(), field->getSignature());
fprintf(log, "\t\t - Modifiers: 0x%x\n", field->getModifiers());
mods = field->getModifiers();
fprintf(log, "\t\t - Modifiers: 0x%x [%s]\n", mods, deserializeFieldModifiers(mods).c_str());
fprintf(log, "\t\t - Fabricated: %s\n", (field->isArbitrary ? "yes" : "no"));
}
auto & methods = clazz->getMethods();
for (auto & method : methods) {
fprintf(log, "\t\t'%s%s':\n", method->getName(), method->getSignature());
fprintf(log, "\t\t - Modifiers: 0x%x\n", method->getModifiers());
mods = method->getModifiers();
fprintf(log, "\t\t - Modifiers: 0x%x [%s]\n", mods, deserializeMethodModifiers(mods).c_str());
fprintf(log, "\t\t - Fabricated: %s\n", (method->isArbitrary ? "yes" : "no"));
}
}
} else {
fprintf(log, "BARON INFO: No classes were registered during execution.\n");
}
return JNI_OK;
}

bool Jvm::isClassBlacklisted(const char * name) {
Expand Down
56 changes: 56 additions & 0 deletions src/util/util.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include "baron/util/util.h"

#define _MODIFIER_CASE(clazz, modifier) \
if ((modifiers & clazz::modifier) == clazz::modifier) {\
smods.append(#modifier);\
}

#include <fake-jni/jvm.h>

namespace Baron {
std::string deserializeClassModifiers(uint32_t modifiers) {
std::string smods;
_MODIFIER_CASE(FakeJni::JClass, PUBLIC)
_MODIFIER_CASE(FakeJni::JClass, PRIVATE)
_MODIFIER_CASE(FakeJni::JClass, PROTECTED)
_MODIFIER_CASE(FakeJni::JClass, STATIC)
_MODIFIER_CASE(FakeJni::JClass, FINAL)
_MODIFIER_CASE(FakeJni::JClass, INTERFACE)
_MODIFIER_CASE(FakeJni::JClass, ABSTRACT)
_MODIFIER_CASE(FakeJni::JClass, SYNTHETIC)
_MODIFIER_CASE(FakeJni::JClass, ANNOTATION)
_MODIFIER_CASE(FakeJni::JClass, ENUM)
return smods;
}

std::string deserializeFieldModifiers(uint32_t modifiers) {
std::string smods;
_MODIFIER_CASE(FakeJni::JMethodID, PUBLIC)
_MODIFIER_CASE(FakeJni::JMethodID, PRIVATE)
_MODIFIER_CASE(FakeJni::JMethodID, PROTECTED)
_MODIFIER_CASE(FakeJni::JMethodID, STATIC)
_MODIFIER_CASE(FakeJni::JMethodID, FINAL)
_MODIFIER_CASE(FakeJni::JMethodID, SYNCHRONIZED)
_MODIFIER_CASE(FakeJni::JMethodID, BRIDGE)
_MODIFIER_CASE(FakeJni::JMethodID, VARARGS)
_MODIFIER_CASE(FakeJni::JMethodID, NATIVE)
_MODIFIER_CASE(FakeJni::JMethodID, ABSTRACT)
_MODIFIER_CASE(FakeJni::JMethodID, STRICT)
_MODIFIER_CASE(FakeJni::JMethodID, SYNTHETIC)
return smods;
}

std::string deserializeMethodModifiers(uint32_t modifiers) {
std::string smods;
_MODIFIER_CASE(FakeJni::JFieldID, PUBLIC)
_MODIFIER_CASE(FakeJni::JFieldID, PRIVATE)
_MODIFIER_CASE(FakeJni::JFieldID, PROTECTED)
_MODIFIER_CASE(FakeJni::JFieldID, STATIC)
_MODIFIER_CASE(FakeJni::JFieldID, FINAL)
_MODIFIER_CASE(FakeJni::JFieldID, VOLATILE)
_MODIFIER_CASE(FakeJni::JFieldID, TRANSIENT)
_MODIFIER_CASE(FakeJni::JFieldID, SYNTHETIC)
_MODIFIER_CASE(FakeJni::JFieldID, ENUM)
return smods;
}
}

0 comments on commit 4049b27

Please sign in to comment.