USING: tools.test namespaces assocs alien.syntax kernel\r
-compiler.errors accessors alien alien.c-types ;\r
-FROM: alien.libraries => add-library ;\r
+compiler.errors accessors alien alien.c-types alien.strings\r
+debugger literals ;\r
+FROM: alien.libraries => add-library load-library ;\r
IN: compiler.tests.linkage-errors\r
\r
! Regression: calling an undefined function would raise a protection fault\r
FUNCTION: void this_does_not_exist ( ) ;\r
\r
-[ this_does_not_exist ] [ { "kernel-error" 9 f f } = ] must-fail-with\r
+[ this_does_not_exist ] try\r
+\r
+[ this_does_not_exist ] [\r
+ { "kernel-error" 9 $[ "this_does_not_exist" string>symbol ] f }\r
+ =\r
+] must-fail-with\r
\r
[ T{ no-such-symbol { name "this_does_not_exist" } } ]\r
[ \ this_does_not_exist linkage-errors get at error>> ] unit-test\r
\r
FUNCTION: void no_such_function ( ) ;\r
\r
+[ no_such_function ] try\r
+\r
+[ no_such_function ] [\r
+ {\r
+ "kernel-error" 9\r
+ $[ "no_such_function" string>symbol ]\r
+ $[ "no_such_library" load-library ]\r
+ }\r
+ =\r
+] must-fail-with\r
+\r
[ T{ no-such-library { name "no_such_library" } } ]\r
[ \ no_such_function linkage-errors get at error>> ] unit-test\r
-! Copyright (C) 2004, 2010 Slava Pestov.
+! Copyright (C) 2004, 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: slots arrays definitions generic hashtables summary io
-kernel math namespaces make prettyprint prettyprint.config
-sequences assocs sequences.private strings io.styles
-io.pathnames vectors words system splitting math.parser
-classes.mixin classes.tuple continuations continuations.private
-combinators generic.math classes.builtin classes compiler.units
-generic.standard generic.single vocabs init kernel.private
-io.encodings accessors math.order destructors source-files
-parser classes.tuple.parser effects.parser lexer generic.parser
-strings.parser vocabs.loader vocabs.parser source-files.errors ;
+USING: alien.strings slots arrays definitions generic hashtables
+summary io kernel math namespaces make prettyprint
+prettyprint.config sequences assocs sequences.private strings
+io.styles io.pathnames vectors words system splitting
+math.parser classes.mixin classes.tuple continuations
+continuations.private combinators generic.math classes.builtin
+classes compiler.units generic.standard generic.single vocabs
+init kernel.private io.encodings accessors math.order
+destructors source-files parser classes.tuple.parser
+effects.parser lexer generic.parser strings.parser vocabs.loader
+vocabs.parser source-files.errors ;
IN: debugger
GENERIC: error-help ( error -- topic )
"FFI error" print drop ;
: undefined-symbol-error. ( obj -- )
- "The image refers to a library or symbol that was not found at load time"
- print drop ;
+ "Cannot resolve C library function" print
+ "Symbol: " write dup third symbol>string print
+ "Library: " write fourth . ;
: stack-underflow. ( obj name -- )
write " stack underflow" print drop ;
-! Copyright (C) 2008, 2010 Slava Pestov.
+! Copyright (C) 2008, 2011 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: arrays sequences kernel kernel.private accessors math
alien.accessors byte-arrays io io.encodings io.encodings.utf8
: dll-path ( dll -- string )
path>> alien>native-string ;
-HOOK: string>symbol* os ( str/seq -- alien )
+GENERIC: string>symbol ( str/seq -- alien )
-M: winnt string>symbol* utf8 string>alien ;
+M: string string>symbol utf8 string>alien ;
-M: wince string>symbol* utf16n string>alien ;
+M: sequence string>symbol [ utf8 string>alien ] map ;
-M: unix string>symbol* utf8 string>alien ;
-
-GENERIC: string>symbol ( str -- alien )
-
-M: string string>symbol string>symbol* ;
-
-M: sequence string>symbol [ string>symbol* ] map ;
+: symbol>string ( alien -- str )
+ utf8 alien>string ;
[
8 special-object utf8 alien>string string>cpu \ cpu set-global
ctx->push(allot_alien(ffi_dlsym_raw(NULL,sym)));
}
-
/* close a native library handle */
void factor_vm::primitive_dlclose()
{
void factor_vm::scrub_return_address()
{
- stack_frame *top = ctx->callstack_top;
- stack_frame *bottom = ctx->callstack_bottom;
- stack_frame *frame = bottom - 1;
-
- while(frame >= top && frame_successor(frame) >= top)
- frame = frame_successor(frame);
-
+ stack_frame *frame = innermost_stack_frame(ctx->callstack_top,
+ ctx->callstack_bottom);
set_frame_offset(frame,0);
}
ctx->push(accum.frames.elements.value());
}
-stack_frame *factor_vm::innermost_stack_frame(callstack *stack)
+stack_frame *factor_vm::innermost_stack_frame(stack_frame *bottom, stack_frame *top)
{
- stack_frame *top = stack->top();
- stack_frame *bottom = stack->bottom();
stack_frame *frame = bottom - 1;
while(frame >= top && frame_successor(frame) >= top)
Used by the single stepper. */
void factor_vm::primitive_innermost_stack_frame_executing()
{
- stack_frame *frame = innermost_stack_frame(untag_check<callstack>(ctx->pop()));
+ callstack *stack = untag_check<callstack>(ctx->pop());
+ stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top());
ctx->push(frame_executing_quot(frame));
}
void factor_vm::primitive_innermost_stack_frame_scan()
{
- stack_frame *frame = innermost_stack_frame(untag_check<callstack>(ctx->pop()));
+ callstack *stack = untag_check<callstack>(ctx->pop());
+ stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top());
ctx->push(frame_scan(frame));
}
jit_compile_quot(quot.value(),true);
- stack_frame *inner = innermost_stack_frame(callstack.untagged());
+ stack_frame *inner = innermost_stack_frame(callstack->bottom(), callstack->top());
cell offset = frame_offset(inner);
inner->entry_point = quot->entry_point;
set_frame_offset(inner,offset);
}
}
-/* References to undefined symbols are patched up to call this function on
-image load */
-void factor_vm::undefined_symbol()
-{
- general_error(ERROR_UNDEFINED_SYMBOL,false_object,false_object);
-}
-
-void undefined_symbol()
-{
- return current_vm()->undefined_symbol();
-}
-
/* Look up an external library symbol referenced by a compiled code block */
-cell factor_vm::compute_dlsym_address(array *literals, cell index)
+cell factor_vm::compute_dlsym_address(array *parameters, cell index)
{
- cell symbol = array_nth(literals,index);
- cell library = array_nth(literals,index + 1);
+ cell symbol = array_nth(parameters,index);
+ cell library = array_nth(parameters,index + 1);
dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
}
#ifdef FACTOR_PPC
-cell factor_vm::compute_dlsym_toc_address(array *literals, cell index)
+cell factor_vm::compute_dlsym_toc_address(array *parameters, cell index)
{
- cell symbol = array_nth(literals,index);
- cell library = array_nth(literals,index + 1);
+ cell symbol = array_nth(parameters,index);
+ cell library = array_nth(parameters,index + 1);
dll *d = (to_boolean(library) ? untag<dll>(library) : NULL);
}
#endif
-
cell factor_vm::compute_vm_address(cell arg)
{
return (cell)this + untag_fixnum(arg);
void factor_vm::store_external_address(instruction_operand op)
{
- code_block *compiled = op.parent_code_block();
+ code_block *compiled = op.compiled;
array *parameters = (to_boolean(compiled->parameters) ? untag<array>(compiled->parameters) : NULL);
- cell index = op.parameter_index();
+ cell index = op.index;
switch(op.rel_type())
{
op.store_value(parent->compute_entry_point_pic_tail_address(next_literal()));
break;
case RT_HERE:
- op.store_value(parent->compute_here_address(next_literal(),op.rel_offset(),op.parent_code_block()));
+ op.store_value(parent->compute_here_address(next_literal(),op.rel_offset(),op.compiled));
break;
case RT_UNTAGGED:
op.store_value(untag_fixnum(next_literal()));
return compiled;
}
+/* Find the RT_DLSYM relocation nearest to the given return address. */
+struct find_symbol_at_address_visitor {
+ factor_vm *parent;
+ cell return_address;
+ cell symbol;
+ cell library;
+
+ find_symbol_at_address_visitor(factor_vm *parent_, cell return_address_) :
+ parent(parent_), return_address(return_address_),
+ symbol(false_object), library(false_object) { }
+
+ void operator()(instruction_operand op)
+ {
+ if(op.rel_type() == RT_DLSYM && op.pointer < return_address)
+ {
+ code_block *compiled = op.compiled;
+ array *parameters = untag<array>(compiled->parameters);
+ cell index = op.index;
+ symbol = array_nth(parameters,index);
+ library = array_nth(parameters,index + 1);
+ }
+ }
+};
+
+/* References to undefined symbols are patched up to call this function on
+image load. It finds the symbol and library, and throws an error. */
+void factor_vm::undefined_symbol()
+{
+ stack_frame *frame = innermost_stack_frame(ctx->callstack_bottom,
+ ctx->callstack_top);
+ code_block *compiled = frame_code(frame);
+ cell return_address = (cell)FRAME_RETURN_ADDRESS(frame, this);
+ find_symbol_at_address_visitor visitor(this, return_address);
+ compiled->each_instruction_operand(visitor);
+ if (!to_boolean(visitor.symbol))
+ critical_error("Can't find RT_DLSYM at return address", return_address);
+ else
+ general_error(ERROR_UNDEFINED_SYMBOL,visitor.symbol,visitor.library);
+}
+
+void undefined_symbol()
+{
+ return current_vm()->undefined_symbol();
+}
+
}
}
};
+VM_C_API void undefined_symbol(void);
}
void operator()(instruction_operand op)
{
- code_block *compiled = op.parent_code_block();
+ code_block *compiled = op.compiled;
cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - fixup.code_offset;
switch(op.rel_type())
return rel.rel_offset();
}
- cell parameter_index()
- {
- return index;
- }
-
- code_block *parent_code_block()
- {
- return compiled;
- }
-
fixnum load_value_2_2();
fixnum load_value_2_2_2_2();
fixnum load_value_masked(cell mask, cell bits, cell shift);
void set_frame_offset(stack_frame *frame, cell offset);
void scrub_return_address();
void primitive_callstack_to_array();
- stack_frame *innermost_stack_frame(callstack *stack);
+ stack_frame *innermost_stack_frame(stack_frame *bottom, stack_frame *top);
void primitive_innermost_stack_frame_executing();
void primitive_innermost_stack_frame_scan();
void primitive_set_innermost_stack_frame_quot();