1

For example, in C, I have something like this declared:

extern char _binary_res_txt_start[];

It came from this command:

ld -r -b binary -o binary.o res.txt

How can I get a Ptr in Haskell that points there? If it were a function, I'd do something like foreign import ccall "&exp" a_exp :: FunPtr (Double -> Double), but I don't think that works for variables.

mxvd
  • 13
  • 5
  • Do you really need to load the data from an actual `.o` file for some reason, or is just the point that you want the data hard-baked into the executable in the end? In that case, there are better routes. – leftaroundabout Apr 30 '20 at 13:58
  • I need data from an object file – mxvd Apr 30 '20 at 14:12
  • 1
    There is a way to link a function from an object file `foreign import ccall "&exp" a_exp :: FunPtr (Double -> Double)` but how to link a data block? – mxvd Apr 30 '20 at 14:16
  • @mxvd I incorporated your comment into the question, and also tried to simplify to get to the core of it. Let me know if I interpreted everything correctly. – Joseph Sible-Reinstate Monica Apr 30 '20 at 15:40

1 Answers1

1

The foreign import syntax works for variables too, as long as you use &. You can then use peekCString or packCString to read it (or peekCStringLen or packCStringLen if it's not null-terminated but you know its length). Here's a full example:

printf 'foo\0bar' > res.txt
ld -r -b binary -o binary.o res.txt
extern char _binary_res_txt_start[];
extern char _binary_res_txt_end[];
import Foreign.C.Types
import Foreign.C.String
import Foreign.Ptr

foreign import ccall "&_binary_res_txt_start" txt_start :: Ptr CChar
foreign import ccall "&_binary_res_txt_end" txt_end :: Ptr CChar

main = do
  str <- peekCStringLen (txt_start, txt_end `minusPtr` txt_start)
  print str
"foo\NULbar"

Note that while ld -b binary also produces a _binary_res_txt_size symbol, it's no longer useful now that ASLR is a thing. See Why doesn't a linked binary file's _size symbol work correctly? for details on that.