[LLVMdev] [BUG x2] getPointerToGlobal is broken

Ramkumar Ramachandra artagnon at gmail.com
Sun Dec 21 17:11:07 PST 2014


Hi,

Yes, I know getPointerToGlobal is deprecated, but it's the only
interface we have in the OCaml world. So this is an investigation to
see if the newer interfaces, specifically getGlobalValueAddress,
suffers from the same problems. The first bug is fun; if you have emit
two anonymous functions, and pass gptg their function objects to get
the value via Ctypes, the second gtpg grabs the value of the first
function:

diff --git a/test/Bindings/OCaml/executionengine.ml
b/test/Bindings/OCaml/executionengine.ml
index 893f988..6e4a5ad 100644
--- a/test/Bindings/OCaml/executionengine.ml
+++ b/test/Bindings/OCaml/executionengine.ml
@@ -42,6 +42,22 @@ let define_plus m =
   ignore (build_ret add b);
   fn

+let define_anon1 m =
+  let fn = define_function "" (function_type i32_type [| i32_type;
+                                                         i32_type |]) m in
+  let b = builder_at_end (global_context ()) (entry_block fn) in
+  let add = build_add (param fn 0) (param fn 1) "sum" b in
+  ignore (build_ret add b);
+  fn
+
+let define_anon2 m =
+  let fn = define_function "" (function_type i32_type [| i32_type;
+                                                         i32_type |]) m in
+  let b = builder_at_end (global_context ()) (entry_block fn) in
+  let add = build_sub (param fn 0) (param fn 1) "diff" b in
+  ignore (build_ret add b);
+  fn
+
 let test_executionengine () =
   let open Ctypes in

@@ -51,6 +67,8 @@ let test_executionengine () =

   (* add plus *)
   let plus = define_plus m in
+  let anon1 = define_anon1 m in
+  let anon2 = define_anon2 m in

   (* add module *)
   let m2 = create_module (global_context ()) "test_module2" in
@@ -78,6 +96,13 @@ let test_executionengine () =
   let cplus   = get_pointer_to_global plus cplusty ee in
   if 4l <> cplus 2l 2l then bomb "plus didn't work";

+  (* call anon1 and anon2 *)
+  let canonty = Foreign.funptr (int32_t @-> int32_t @-> returning int32_t) in
+  let canon1  = get_pointer_to_global anon1 canonty ee in
+  let canon2  = get_pointer_to_global anon2 canonty ee in
+  if 4l <> canon1 2l 2l then bomb "anon1 didn't work";
+  if 0l <> canon2 2l 2l then bomb "anon2 didn't work";
+
   (* call getglobal *)
   (* let cgetglobalty = Foreign.funptr (void @-> returning int32_t) in
   let cgetglobal   = get_pointer_to_global getglobal cgetglobalty ee in

anon2 reports the same value as anon1. Since ggva clearly asks for a
string identifier, this confusion doesn't apply to it. Nevertheless,
it should be noted that it's impossible to grab two anonymous
functions uniquely via this interface.

I'm still working on uncovering the details of this next bug; gtpg
cannot be interspersed with define_function statements; a SIGSEGV
results otherwise:

diff --git a/test/Bindings/OCaml/executionengine.ml
b/test/Bindings/OCaml/executionengine.ml
index 893f988..a4c8123 100644
--- a/test/Bindings/OCaml/executionengine.ml
+++ b/test/Bindings/OCaml/executionengine.ml
@@ -42,6 +42,22 @@ let define_plus m =
   ignore (build_ret add b);
   fn

+let define_ooo1 m =
+  let fn = define_function "ooo1" (function_type i32_type [| i32_type;
+                                                         i32_type |]) m in
+  let b = builder_at_end (global_context ()) (entry_block fn) in
+  let add = build_add (param fn 0) (param fn 1) "sum" b in
+  ignore (build_ret add b);
+  fn
+
+let define_ooo2 m =
+  let fn = define_function "ooo2" (function_type i32_type [| i32_type;
+                                                         i32_type |]) m in
+  let b = builder_at_end (global_context ()) (entry_block fn) in
+  let add = build_sub (param fn 0) (param fn 1) "diff" b in
+  ignore (build_ret add b);
+  fn
+
 let test_executionengine () =
   let open Ctypes in

@@ -78,6 +94,14 @@ let test_executionengine () =
   let cplus   = get_pointer_to_global plus cplusty ee in
   if 4l <> cplus 2l 2l then bomb "plus didn't work";

+  (* define and execute out of order *)
+  let ooo1 = define_ooo1 m in
+  let cooo1  = get_pointer_to_global ooo1 cplusty ee in
+  if 4l <> cooo1 2l 2l then bomb "anon1 didn't work";
+  let ooo2 = define_ooo2 m in
+  let cooo2  = get_pointer_to_global ooo2 cplusty ee in
+  if 0l <> cooo2 2l 2l then bomb "anon2 didn't work";
+
   (* call getglobal *)
   (* let cgetglobalty = Foreign.funptr (void @-> returning int32_t) in
   let cgetglobal   = get_pointer_to_global getglobal cgetglobalty ee in

I'll try to reproduce this with ggva using the C++ API so that it's clearer.

Thanks.

Ram



More information about the llvm-dev mailing list