Compiling Ruby Inline C code - resolving errors - ruby

I am trying to get this Ruby inline C code http://pastie.org/2825882 to work. The code works in vanilla C, but here I get errors and warnings. What causes this error?
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
Also, why do I get the following error?
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
Inspecting the resulting C code ( http://pastie.org/2826036) I fail to see anything wrong with the arguments. But I do also get the following warnings:
./backtrack_inline.rb:73: warning: passing argument 1 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 2 of 'backtrack' makes integer from pointer without a cast
./backtrack_inline.rb:73: warning: passing argument 3 of 'backtrack' makes integer from pointer without a cast

Starting with this:
./backtrack_inline.rb:73: error: too few arguments to function 'backtrack'
If you look at your generated code, the backtrack function is defined on line 29:
static VALUE backtrack(VALUE self, VALUE _ss, VALUE _s, VALUE _p, VALUE _mm, VALUE _ins, VALUE _del) { ... }
It has seven arguments, the original six, plus VALUE self as it has been converted into a method on the Scan class.
The call to this function, on line 67 looks like this:
end = backtrack(ss, s, p, mm, ins, del);
It has only six arguments. RubyInline doesn't convert this to a call to a method on the object, it simply copies it verbatim. This is also where the warnings about makes integer from pointer without a cast come from: the function definition has been converted to take VALUEs, but you're calling with the original types.
The error message says that the error is from line 73 in backtrack_inline.rb because of the directive on line 54 of the generated code:
# line 61 "./backtrack_inline.rb"
which basically tells the compiler to "reset" its line and file values for errors, and treat the next line (55) as being line 61 in the file ./backtrack_inline.rb. The actual line is 67, 12 ahead of 55, but the compiler reports it as being 73, 12 ahead of 61 (the value it was reset to) and from a differnt file. This technique doesn't really work in this case as it doesn't take into account the extra lines added by RubyInline. The actual line in the source is 69.
A simple fix for this is to change the definition of the backtrack function to be just a C function rather than add it as a method on the object. Change builder.c to builder.prefix (on line 38 of your Ruby file). This won't work if you want to have backtrack available as a method on the object in Ruby. If that's the case you might need create another function to be the method, which then wraps the "real" backtrack function.
Next, looking at
./backtrack_inline.rb:67: error: lvalue required as unary '&' operand
This actually refers to line 61 of the generated code, which looks like:
char* s = StringValuePtr(rb_iv_get(self, "#seq"));
StringValuePtr is a macro which is defined as:
#define StringValue(v) rb_string_value(&(v))
This is where the & in lvalue required as unary '&' operand comes from. You need to add a local variable to be the lvalue:
VALUE seq = rb_iv_get(self, "#seq");
char* s = StringValuePtr(seq);
In my case (Mac OS X Snow Leopard, Ruby 1.9.3-p0, RubyInline 3.11.0) these two changes made the script run without errors, but gave the warning:
backtrack_inline.rb:47: warning: implicit conversion shortens 64-bit value into a 32-bit value
This actually refers to line 46 of the ruby file:
return (s - ss) - 1;
s and ss are char *, i.e. 64 bit pointers (on this machine), and the return type of the function is int - 32 bits. Adding an explicit cast fixed this:
return (int)((s - ss) - 1);
It now runs cleanly:
ruby-inline $ ruby backtrack_inline.rb
14
ruby-inline $
(I hope 14 is the correct answer!)
Here's a version of the script with these changes.

OK, the question was also answered at Ruby Forum:
http://www.ruby-forum.com/topic/2959614

Ok... thought a bit more about this.
you are calling a variable end. While this isn't a reserved word in C - and ruby shouldn't be looking at it... perhaps ruby is getting confused?
I'd suggest you have a go at renaming it just in case. Worthwhile trying even just to rule it out.

Related

The called method `...' is defined here

Ruby 2.7 was just released and it comes with these new warnings for "Separation of positional and keyword arguments" (see their Release Post).
I was playing around with it and discovered that there's another warning, which I don't understand.
Example:
def multiply(x:, y:)
x * y
end
args = { x: 2, y: 3 }
multiply(args)
# ./warning.rb:7: warning: Using the last argument as keyword parameters is deprecated; maybe ** should be added to the call
# ./warning.rb:1: warning: The called method `multiply' is defined here
I think the first warning about the deprecation is clear, but the second warning The called method `multiply' is defined here is confusing to me.
What does the second warning mean? Is it related to the first warning?
Both warnings disappear when adding ** to the call (multiply(**args)).
What does the second warning mean? Is it related to the first warning?
There is a single warning with a text split into two lines. It literally says: args should be converted to **args, here is the call that produced this warning, here is its definition for your convenience.

lldb complains about variable named "this"

I'm using Xcode/lldb to debug some C code. But I get this error
(lldb) p (int)g_list_position(start, next)
(int) $0 = 1
(lldb) p (int)g_list_position(start, this)
error: expected unqualified-id
error: invalid use of 'this' outside of a non-static member function
So apparently lldb things "this" is a reference to a class, in spite of it being a perfectly valid var in C (and its value is 0, as it should be). Is there some way to escape this name in lldb?
No, the expression evaluator in lldb wraps your expression (at at a source level) with some C++ to pass the arguments in. The only suggestion I can think of is to get the address in the this pointer and put that in the expression explicitly. It's a goal of the expression evaluation that you can copy a line of source in your program and execute it as an expression in lldb .. but this is a corner case where that does not work - variables in C that are reserved words in C++.

Compilation error in declaration of method which accepts input as block with variable number of arguments

When I am declaring a method like this:
- (void)doAnythingWithThisBlock:(void(^)(NSString *, ... NS_REQUIRES_NIL_TERMINATION))AnythingBlock;
It is giving compilation error:
Expected ')'
but when I am declaring it like this:
- (void)doAnythingWithThisBlock:(void(^)(NSString *, ...))AnythingBlock;
It compiles fine and works as expected
Cannot we use - NS_REQUIRES_NIL_TERMINATION while declaring a method which accepts input as block with variable number of arguments?
I am trying it in XCode 4.2
I guess NS_REQUIRES_NIL_TERMINATION is only for method declarations 1
However you can try to typedef your block to certain type and pass it as an argument: may be clang will eat it then?

trying to find a file/line for: .(eval):289: warning: don't put space before argument parentheses

So, I get this warning when I'm running my tests in ruby/RoR
.(eval):289: warning: don't put space before argument parentheses
I've checked every where (but obvoiusly not) and I can't find the origin of this error.
The above error just pops up inbetween the unit tests ...
Can someone clue me in onto how to find the location of this error?
The file and line number are contained in the backtrace. However, in your case, the warning is inside a string being evaled at runtime. Which means there is no file. (Actually, the eval method does take optional arguments for the file name and line number that should be displayed in a backtrace, but in this case whoever wrote the code in question unfortunately forgot to pass those arguments.)
I fear that you have no other choice than to manually examine every single call to eval in your entire codebase, and that includes Rails, your testing framework, your entire application, your tests, your plugins, your helpers, the ruby standard library, ...
Of course, you should be aware that the problem might not be obvious as in
eval 'foo (bar, baz)'
It could also be something like
def foo(*args)
puts args.join
end
bar = 'Hello'
baz = 'World'
foostr = 'foo' # in one file
barstr = 'bar' # in another file in a different directory
bazstr = 'baz' # in another file in a different directory
argstr = "(#{barstr}, #{bazstr})" # in yet another file
$, = ' ' # in some third-party plugin
str = [foostr, argstr].join # in a fourth file
eval str # somewhere else entirely
eval str, binding, __FILE__, __LINE__ # this is how it *should* be done
Note the difference between the two warning messages: the first one reads exactly like the one you posted, but the second one has the filename instead of (eval) and the line number inside the file instead of the line number inside the eval string.
By the way: the line number 289 in the warning message is the line number inside the evald string! In other words: somewhere in your application there is a string being evald, which is at least 289 lines long! (Actually, it is more likely that this done not in your application but rather in Rails. The Rails router used to be a particularly bad offender, I don't know if this is still the case.)
It sounds to me that there is a rule which forbids a space between a function name and the parentheses enclosing the arguments of the function.
In many languages this would be considered a permissible stylistic variation.
Is the eval mentioned in the warning message, the 'function' being complained about?
Does the number 289 mean anything as a line number?
Could you search your source files for a parenthesis preceded by a space?
Incidentally, the message says warning. What happens if you ignore it?
If it's happening in between the unit tests it might be in a setup or teardown method. Try searching for eval or try reducing the code you are running until the error goes away. Then you'll know where to look (the code you just removed).

How to cast a function name to an address and add offset in LLDB?

Say, I have two adjacent functions subfunc() and main() in the Mach-O executable and want to disassemble all instructions from subfunc() to main()+0x10.
I know I can cast functions to addresses using `(void(*)())subfunc` - isn't there an easier way?
My attempt is as follows, but I get the error message below:
dis -s `(void(*)())subfunc` -e `(void(*)())main+0x10`
error: error: arithmetic on a pointer to the function type 'void ()'
How can I fix this?
This appears to be the correct syntax:
dis --start-address `(void(*)())main` --end-address `(void(*)())main`+0x10
The very small difference between this syntax and the variant you tried is that the +0x10 offset goes outside the backtick characters, i.e. the offset goes after the closing backtick.
FWIW this variant also appears to work correctly:
dis --start-address `(void(*)())main` --end-address 0x10+`(void(*)())main`
Discovery process:
I was unfamiliar with the "backtick" + function cast that you described in your original question so that was a very helpful starting point.
In my case I was trying to set a breakpoint at a function offset inside a shared library and got about as far as this before my search landed me on your question:
breakpoint set --shlib libexample.dylib --address `((void*)some_function)+81`
error: error: function 'some_function' with unknown type must be given a function type
error: 1 errors parsing expression
The use of your function cast hint met the "function type" requirement stated in the error message so I was next able to get to:
print (void(*)())some_function
(void (*)()) $38 = 0x00000001230094d0 (libexample.dylib`some_function)
I then tried the backtick variant which appeared to work but I wanted the value to be displayed in hexadecimal:
print `(void(*)())some_function`
(long) $2 = 4882207952
But when I tried to use the -f hex format option with print I got an error:
print -f hex `(void(*)())some_function`
error: use of undeclared identifier 'f'
error: 1 errors parsing expression
Eventually I noticed the comment 'print' is an abbreviation for 'expression --' at the bottom of the help print output and realised that means it's (apparently?) not possible to use an alternative display format with print because it gets converted into expression -- -f hex ... which is not valid syntax.
Eventually I figured out the required placement & combination of command name, display format and "--" to make it display as desired:
expression -f hex -- `(void(*)())some_function`
(long) $7 = 0x00000001230094d0
For no particular reason (that I can remember) it was at this point I tried placing the offset outside the backticks and it worked!
expression -f hex -- `(void(*)())some_function`+81
(long) $12 = 0x0000000123009521
And it still worked when I tried it with a breakpoint:
breakpoint set --shlib libexample.dylib --address `(void(*)())some_function`+81
Breakpoint 6: where = libexample.dylib`some_function + 81, address = 0x0000000123009521
Then I verified that it also worked with the dis command from your original question:
dis --start-address `(void(*)())some_function` --end-address `(void(*)())some_function`+81
And confirmed that the bare function name was not sufficient:
dis --start-address some_function --end-address `(void(*)())some_function`+81
error: address expression "some_function" evaluation failed
I also re-confirmed that the offset being between the backticks did not work:
dis --start-address `(void(*)())some_function` --end-address `(void(*)())some_function+1`
error: error: arithmetic on a pointer to the function type 'void ()'
error: 1 errors parsing expression
It was at this point that I realised I was able to parse the error message (as it was presumably intended):
[arithmetic on a pointer] [to the function type] ['void ()']
The underlying issue being "arithmetic on a pointer"...
Which further research shows is both "undefined on pointers to function types" and available as a gcc extension:
https://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html
Why is it not allowed to perform arithmetic operations on function pointers?
Should clang and gcc produce a diagnostic message when a program does pointer arithmetic on a function pointer?
Incrementing function pointers
Function pointer arithmetic
How to print the address of a function?
https://github.com/llvm/llvm-project/blob/f804bd586ee58199db4cfb2da8e9ef067425900b/clang/test/Sema/pointer-addition.c
https://reviews.llvm.org/D37042
Which brings us back to the comments by #JasonMolenda & #JimIngham and how the function pointer arithmetic parsing is special-cased.
To my mind the "error: arithmetic on a pointer to the function type..." message you received is at best poor UX & at worst a bug--given that lldb itself essentially displays address references in that manner:
0x1230094f9: jle 0x123009cc2 ; some_function + 2034
I feel similarly about libexample.dylib`some_function + 81 being displayed but AFAICT not being parsed.
In conclusion, this form works:
`(void(*)())some_function`+0x10
Now I just need to figure out why some_function isn't doing what I think it should... :)

Resources