2005-04-16 15:20:36 -07:00
/*
* linux / arch / sparc / mm / extable . c
*/
# include <linux/module.h>
2017-01-10 10:12:55 -05:00
# include <linux/extable.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
void sort_extable ( struct exception_table_entry * start ,
struct exception_table_entry * finish )
{
}
/* Caller knows they are in a range if ret->fixup == 0 */
const struct exception_table_entry *
2017-07-10 15:51:58 -07:00
search_extable ( const struct exception_table_entry * base ,
const size_t num ,
2005-04-16 15:20:36 -07:00
unsigned long value )
{
2017-07-10 15:51:58 -07:00
int i ;
2005-04-16 15:20:36 -07:00
/* Single insn entries are encoded as:
* word 1 : insn address
* word 2 : fixup code address
*
* Range entries are encoded as :
* word 1 : first insn address
* word 2 : 0
* word 3 : last insn address + 4 bytes
* word 4 : fixup code address
*
2009-06-12 21:47:03 -06:00
* Deleted entries are encoded as :
* word 1 : unused
* word 2 : - 1
*
2005-04-16 15:20:36 -07:00
* See asm / uaccess . h for more details .
*/
/* 1. Try to find an exact match. */
2017-07-10 15:51:58 -07:00
for ( i = 0 ; i < num ; i + + ) {
if ( base [ i ] . fixup = = 0 ) {
2005-04-16 15:20:36 -07:00
/* A range entry, skip both parts. */
2017-07-10 15:51:58 -07:00
i + + ;
2005-04-16 15:20:36 -07:00
continue ;
}
2009-06-12 21:47:03 -06:00
/* A deleted entry; see trim_init_extable */
2017-07-10 15:51:58 -07:00
if ( base [ i ] . fixup = = - 1 )
2009-06-12 21:47:03 -06:00
continue ;
2017-07-10 15:51:58 -07:00
if ( base [ i ] . insn = = value )
return & base [ i ] ;
2005-04-16 15:20:36 -07:00
}
/* 2. Try to find a range match. */
2017-07-10 15:51:58 -07:00
for ( i = 0 ; i < ( num - 1 ) ; i + + ) {
if ( base [ i ] . fixup )
2005-04-16 15:20:36 -07:00
continue ;
2017-07-10 15:51:58 -07:00
if ( base [ i ] . insn < = value & & base [ i + 1 ] . insn > value )
return & base [ i ] ;
2005-04-16 15:20:36 -07:00
2017-07-10 15:51:58 -07:00
i + + ;
2005-04-16 15:20:36 -07:00
}
return NULL ;
}
2009-06-12 21:47:03 -06:00
# ifdef CONFIG_MODULES
/* We could memmove them around; easier to mark the trimmed ones. */
void trim_init_extable ( struct module * m )
{
unsigned int i ;
bool range ;
for ( i = 0 ; i < m - > num_exentries ; i + = range ? 2 : 1 ) {
range = m - > extable [ i ] . fixup = = 0 ;
if ( within_module_init ( m - > extable [ i ] . insn , m ) ) {
m - > extable [ i ] . fixup = - 1 ;
if ( range )
m - > extable [ i + 1 ] . fixup = - 1 ;
}
if ( range )
i + + ;
}
}
# endif /* CONFIG_MODULES */
2005-04-16 15:20:36 -07:00
/* Special extable search, which handles ranges. Returns fixup */
unsigned long search_extables_range ( unsigned long addr , unsigned long * g2 )
{
const struct exception_table_entry * entry ;
entry = search_exception_tables ( addr ) ;
if ( ! entry )
return 0 ;
/* Inside range? Fix g2 and return correct fixup */
if ( ! entry - > fixup ) {
* g2 = ( addr - entry - > insn ) / 4 ;
return ( entry + 1 ) - > fixup ;
}
return entry - > fixup ;
}