diff --git a/basis/compiler/tests/linkage-errors.factor b/basis/compiler/tests/linkage-errors.factor index 94c0a1d5aa..687ec71e29 100644 --- a/basis/compiler/tests/linkage-errors.factor +++ b/basis/compiler/tests/linkage-errors.factor @@ -1,12 +1,18 @@ USING: tools.test namespaces assocs alien.syntax kernel -compiler.errors accessors alien alien.c-types ; -FROM: alien.libraries => add-library ; +compiler.errors accessors alien alien.c-types alien.strings +debugger literals ; +FROM: alien.libraries => add-library load-library ; IN: compiler.tests.linkage-errors ! Regression: calling an undefined function would raise a protection fault FUNCTION: void this_does_not_exist ( ) ; -[ this_does_not_exist ] [ { "kernel-error" 9 f f } = ] must-fail-with +[ this_does_not_exist ] try + +[ this_does_not_exist ] [ + { "kernel-error" 9 $[ "this_does_not_exist" string>symbol ] f } + = +] must-fail-with [ T{ no-such-symbol { name "this_does_not_exist" } } ] [ \ this_does_not_exist linkage-errors get at error>> ] unit-test @@ -17,5 +23,16 @@ LIBRARY: no_such_library FUNCTION: void no_such_function ( ) ; +[ no_such_function ] try + +[ no_such_function ] [ + { + "kernel-error" 9 + $[ "no_such_function" string>symbol ] + $[ "no_such_library" load-library ] + } + = +] must-fail-with + [ T{ no-such-library { name "no_such_library" } } ] [ \ no_such_function linkage-errors get at error>> ] unit-test diff --git a/basis/debugger/debugger.factor b/basis/debugger/debugger.factor index b3eb1d4ad0..0ac1078e93 100755 --- a/basis/debugger/debugger.factor +++ b/basis/debugger/debugger.factor @@ -1,15 +1,16 @@ -! 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 ) @@ -107,8 +108,9 @@ HOOK: signal-error. os ( obj -- ) "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 ; diff --git a/core/alien/strings/strings.factor b/core/alien/strings/strings.factor index 435ceb2a96..fce6c40562 100644 --- a/core/alien/strings/strings.factor +++ b/core/alien/strings/strings.factor @@ -1,4 +1,4 @@ -! 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 @@ -51,19 +51,14 @@ M: windows native-string-encoding utf16n ; : 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 diff --git a/vm/alien.cpp b/vm/alien.cpp index 98b68b45af..9fa48cf66f 100755 --- a/vm/alien.cpp +++ b/vm/alien.cpp @@ -160,7 +160,6 @@ void factor_vm::primitive_dlsym_raw() ctx->push(allot_alien(ffi_dlsym_raw(NULL,sym))); } - /* close a native library handle */ void factor_vm::primitive_dlclose() { diff --git a/vm/callstack.cpp b/vm/callstack.cpp index 5bec7f17cf..5a7fbb8c03 100755 --- a/vm/callstack.cpp +++ b/vm/callstack.cpp @@ -129,13 +129,8 @@ void factor_vm::set_frame_offset(stack_frame *frame, cell offset) 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); } @@ -191,10 +186,8 @@ void factor_vm::primitive_callstack_to_array() 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) @@ -207,13 +200,15 @@ stack_frame *factor_vm::innermost_stack_frame(callstack *stack) Used by the single stepper. */ void factor_vm::primitive_innermost_stack_frame_executing() { - stack_frame *frame = innermost_stack_frame(untag_check(ctx->pop())); + callstack *stack = untag_check(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(ctx->pop())); + callstack *stack = untag_check(ctx->pop()); + stack_frame *frame = innermost_stack_frame(stack->bottom(), stack->top()); ctx->push(frame_scan(frame)); } @@ -227,7 +222,7 @@ void factor_vm::primitive_set_innermost_stack_frame_quot() 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); diff --git a/vm/code_blocks.cpp b/vm/code_blocks.cpp index 1f8be8b96a..c464416fb6 100755 --- a/vm/code_blocks.cpp +++ b/vm/code_blocks.cpp @@ -140,23 +140,11 @@ void factor_vm::update_word_references(code_block *compiled, bool reset_inline_c } } -/* 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(library) : NULL); @@ -197,10 +185,10 @@ cell factor_vm::compute_dlsym_address(array *literals, cell index) } #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(library) : NULL); @@ -240,7 +228,6 @@ cell factor_vm::compute_dlsym_toc_address(array *literals, cell index) } #endif - cell factor_vm::compute_vm_address(cell arg) { return (cell)this + untag_fixnum(arg); @@ -248,9 +235,9 @@ cell factor_vm::compute_vm_address(cell 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(compiled->parameters) : NULL); - cell index = op.parameter_index(); + cell index = op.index; switch(op.rel_type()) { @@ -327,7 +314,7 @@ struct initial_code_block_visitor { 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())); @@ -451,4 +438,49 @@ code_block *factor_vm::add_code_block(code_block_type type, cell code_, cell lab 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(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(); +} + } diff --git a/vm/code_blocks.hpp b/vm/code_blocks.hpp index f20e2da372..cd7d1ea5ae 100644 --- a/vm/code_blocks.hpp +++ b/vm/code_blocks.hpp @@ -83,4 +83,5 @@ struct code_block } }; +VM_C_API void undefined_symbol(void); } diff --git a/vm/image.cpp b/vm/image.cpp index 4643d89779..696d9ee1b4 100755 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -160,7 +160,7 @@ struct startup_code_block_relocation_visitor { 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()) diff --git a/vm/instruction_operands.hpp b/vm/instruction_operands.hpp index 563972ab17..a5286d5324 100644 --- a/vm/instruction_operands.hpp +++ b/vm/instruction_operands.hpp @@ -143,16 +143,6 @@ struct instruction_operand { 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); diff --git a/vm/vm.hpp b/vm/vm.hpp index 28e9c8c1aa..aab6864f20 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -593,7 +593,7 @@ struct factor_vm 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();