⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bfdreflect.cpp

📁 java 反射机制详解示例,实现类属性及方法修改
💻 CPP
字号:
#include <alloca.h>
#include <assert.h>
#include "bfdreflect.h"


RTTIBfdRepository RTTIBfdRepository::theRepository;

void RTTIStackFrameMethodType::calculateFrameSize()
{
    int frameSize = 0;
    for (int i = 0; i < nParams; i++) { 
	switch (paramTypes[i]->getTag()) { 
	  case RTTI_BOOL:
	  case RTTI_CHAR:
	  case RTTI_UCHAR:
	  case RTTI_SCHAR:
	  case RTTI_SHORT:
	  case RTTI_USHORT:
	  case RTTI_INT:
	  case RTTI_UINT:
	    frameSize += sizeof(int);
	    break;
	  case RTTI_LONG:
	  case RTTI_ULONG:
	    frameSize += sizeof(long);
	  case RTTI_FLOAT:
	  case RTTI_DOUBLE:
	    frameSize += sizeof(double);
	    break;
	  case RTTI_ARRAY:
	  case RTTI_PTR:
	    frameSize += sizeof(void*);
	    break;
	}
    }
    if (!isStatic) { 
	frameSize += sizeof(void*);
    }
    this->frameSize = frameSize;
}


void RTTIStackFrameMethodType::invoke(void* result, void* obj, void* params[])
{
    assert (methodAddress != NULL);
    char* fp;
    char* frame = NULL;
    if (frameSize != 0) { 
	frame = (char*)alloca(frameSize);
    }
    fp = frame;
    if (!isStatic) { 
	*(void**)fp = obj;
	fp += sizeof(void*);
    }
    for (int i = 0, n = nParams; i < n; i++) { 
	switch (paramTypes[i]->getTag()) { 
	  case RTTI_CHAR:
	    *(int*)fp = *(char*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_SCHAR:
	    *(int*)fp = *(signed char*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_UCHAR:
	    *(int*)fp = *(unsigned char*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_SHORT:
	    *(int*)fp = *(short*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_USHORT:
	    *(int*)fp = *(unsigned short*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_INT:
	  case RTTI_UINT:
	    *(int*)fp = *(int*)params[i];
	    fp += sizeof(int);
	    break;
	  case RTTI_LONG:
	  case RTTI_ULONG:
	    *(long*)fp = *(long*)params[i];
	    fp += sizeof(long);
	    break;
	  case RTTI_FLOAT:
	    *(double*)fp = *(float*)params[i];
	    fp += sizeof(double);
	    break;
	  case RTTI_DOUBLE:
	    *(double*)fp = *(double*)params[i];
	    fp += sizeof(double);
	    break;
	  case RTTI_PTR:
	  case RTTI_ARRAY:
	    *(void**)fp = *(void**)params[i];
	    fp += sizeof(void*);
	    break;
	}
    }
    switch (returnType->getTag()) { 
      case RTTI_VOID:
	(*(void(*)())methodAddress)();
	break;
      case RTTI_CHAR:
      case RTTI_SCHAR:
      case RTTI_UCHAR:
	*(char*)result = (*(char(*)())methodAddress)();
	break;
      case RTTI_SHORT:
      case RTTI_USHORT:
	*(short*)result = (*(short(*)())methodAddress)();
	break;	
      case RTTI_INT:
      case RTTI_UINT:
	*(int*)result = (*(int(*)())methodAddress)();
	break;	
      case RTTI_LONG:
      case RTTI_ULONG:
	*(long*)result = (*(long(*)())methodAddress)();
	break;	
      case RTTI_FLOAT:
	*(float*)result = (*(float(*)())methodAddress)();
	break;
      case RTTI_DOUBLE:
	*(double*)result = (*(double(*)())methodAddress)();
	break;	
      case RTTI_PTR:
      case RTTI_ARRAY:
	*(void**)result = (*(void*(*)())methodAddress)();
	break;
      default:
	break;
    }
}

int RTTIBfdRepository::getVisibility(enum debug_visibility visibility)
{ 
    switch (visibility) {
      case DEBUG_VISIBILITY_PUBLIC:
	return RTTI_FLD_PUBLIC;
	break;
      case DEBUG_VISIBILITY_PROTECTED:
	return RTTI_FLD_PROTECTED;
	break;
      case DEBUG_VISIBILITY_PRIVATE:
	return RTTI_FLD_PRIVATE;
	break;
    }
    return 0;
}

int RTTIBfdRepository::getTypeQualifiers(debug_type* type)
{
    switch (type->kind) {
      case DEBUG_KIND_VOLATILE:
	return RTTI_FLD_VOLATILE | getTypeQualifiers(type->u.kvolatile);
      case DEBUG_KIND_CONST:
	return RTTI_FLD_CONST | getTypeQualifiers(type->u.kconst);
      default:
	return 0;
    }
}
    

RTTIType* RTTIBfdRepository::getType(debug_type* type)
{
    RTTIClassDescriptor* cls;

    switch (type->kind) {
      case DEBUG_KIND_VOID:
	return &RTTIType::voidType;
      case DEBUG_KIND_ENUM:
      case DEBUG_KIND_INT:
	if (type->u.kint) { 
	    if (type->size == sizeof(char)) { 
	        return &RTTIType::charType;
	    } else if (type->size == sizeof(short)) { 
	        return &RTTIType::shortType;
	    } else if (type->size == sizeof(int)) { 
	        return &RTTIType::intType;
	    } else if (type->size == sizeof(long)) { 
	        return &RTTIType::longType;
	    } else {
	        return &RTTIType::unknownType;
	    }
	} else {
	    if (type->size == sizeof(char)) { 
	        return &RTTIType::ucharType;
	    } else if (type->size == sizeof(short)) { 
	        return &RTTIType::ushortType;
	    } else if (type->size == sizeof(int)) { 
	        return &RTTIType::uintType;
	    } else if (type->size == sizeof(long)) { 
	        return &RTTIType::ulongType;
	    } else {
	        return &RTTIType::unknownType;
	    }
	}
	/* Floating point.  */
      case DEBUG_KIND_FLOAT:
	return type->size == sizeof(float) ? &RTTIType::floatType : &RTTIType::doubleType;      
	/* Boolean.  */
      case DEBUG_KIND_BOOL:
	return &RTTIType::boolType;
      case DEBUG_KIND_INDIRECT:
	if (*type->u.kindirect->slot != NULL) { 
	    return getType(*type->u.kindirect->slot);
	}
	cls = findClass(type->u.kindirect->tag);
	if (cls == NULL) { 
	    printf("Failed to find tag '%s'\n", type->u.kindirect->tag);
	    return &RTTIType::unknownType;
	}
	return cls;
      case DEBUG_KIND_NAMED:
      case DEBUG_KIND_TAGGED:
	if (type->u.knamed->type->kind == DEBUG_KIND_CLASS ||
	    type->u.knamed->type->kind == DEBUG_KIND_STRUCT)
	{
	    cls = findClass(type->u.knamed->name->name);
	    if (cls == NULL) { 
		printf("Failed to find class '%s'\n", type->u.knamed->name->name);
		return &RTTIType::unknownType;
	    }
	    return cls;
	} else { 
	    return getType(type->u.knamed->type);
	}
      case DEBUG_KIND_FUNCTION:
        return &RTTIType::voidType;
      case DEBUG_KIND_POINTER:
	return new RTTIPtrType(getType(type->u.kpointer));
      case DEBUG_KIND_REFERENCE:
	return new RTTIPtrType(getType(type->u.kreference));
      case DEBUG_KIND_ARRAY:
	return new RTTIArrayType(getType(type->u.karray->element_type), type->u.karray->upper - type->u.karray->lower + 1);
      case DEBUG_KIND_VOLATILE:
	return getType(type->u.kvolatile);
      case DEBUG_KIND_CONST:
	return getType(type->u.kconst);
      default:
	// printf("Unknown type %d\n", type->kind);
	return &RTTIType::unknownType;
    }
}


void RTTIBfdRepository::loadClass(debug_type* type) 
{
    debug_type* real = debug_get_real_type(handle, type, NULL);
    if (real->u.kclass != NULL) {
	RTTIClassDescriptor* cls = new RTTIClassDescriptor(type->u.knamed->name->name, 
							   type->size, 
							   0);	     
	addClass(cls);
    }
}



void RTTIBfdRepository::readClass(debug_type* type) 
{
    debug_type* real = debug_get_real_type(handle, type, NULL);

    if (real->u.kclass != NULL) {
	int i;
	char const* className = type->u.knamed->name->name;
	RTTIClassDescriptor* cls = findClass(className);
	if (cls == NULL || cls->initialized) {
	    return;
	}
	RTTIFieldDescriptor **fdp = &cls->fieldList;	
	if (real->u.kclass->baseclasses != NULL) { 
	    for (i = 0; real->u.kclass->baseclasses[i] != NULL; i++) {
		debug_baseclass* b = real->u.kclass->baseclasses[i];
		char const* baseClassName = b->type->kind == DEBUG_KIND_NAMED ? b->type->u.knamed->name->name
		    : b->type->u.kindirect->tag;
		RTTIClassDescriptor* baseClass = findClass(baseClassName);
		int flags = getVisibility(b->visibility);
		if (b->is_virtual) { 
		    flags |= RTTI_FLD_VIRTUAL;
		}
		RTTIFieldDescriptor* fd = new RTTIFieldDescriptor(baseClassName, b->bitpos/8,
								  b->type->size, flags,
								  new RTTIDerivedType(baseClass));
		*fdp = fd;
		fdp = &fd->next;
	    }
	}

	if (real->u.kclass->fields != NULL) {
	    for (i = 0; real->u.kclass->fields[i] != NULL; i++) {
		debug_field* f = real->u.kclass->fields[i];
		int flags = getTypeQualifiers(f->type) | getVisibility(f->visibility);
		if (f->static_member) { 
		    flags |= RTTI_FLD_STATIC;
		}
		RTTIFieldDescriptor* fd = new RTTIFieldDescriptor(f->name, f->u.f.bitpos/8, f->u.f.bitsize/8, flags, getType(f->type));
		*fdp = fd;
		fdp = &fd->next;
	    }
	}
	*fdp = NULL;

	RTTIMethodDescriptor **mdp = &cls->methodList;	

	if (real->u.kclass->methods != NULL) {	
	    for (i = 0; real->u.kclass->methods[i] != NULL; i++) {
		debug_method* m = real->u.kclass->methods[i];
		unsigned int j, k, n;	    
		int commonFlags = (strcmp(constructorName, m->name) == 0 || strcmp(className, m->name) == 0)
		    ? RTTI_MTH_CONSTRUCTOR : 0;
		
		for (j = 0; m->variants[j] != NULL; j++) {
		    debug_method_variant* v = m->variants[j];
		    int flags = commonFlags | getVisibility(v->visibility);
		    if (v->voffset == VOFFSET_STATIC_METHOD) {
			flags |= RTTI_MTH_STATIC;
		    }
		    if (v->constp) { 
			flags |= RTTI_MTH_CONST;
		    }
		    RTTIStackFrameMethodType* type = new RTTIStackFrameMethodType();
		    type->returnType = getType(v->type->u.kmethod->return_type);
		    type->methodClass = cls;
		    type->methodAddress = (void*)v->address;
		    RTTIMethodDescriptor* md = new RTTIMethodDescriptor(m->name, flags, type);
		    if (v->type->u.kmethod->arg_types != NULL) {
			for (k = 0; v->type->u.kmethod->arg_types[k] != NULL; k++);
			int n = 0;
#if defined(__GNUC__) && __GNUC_MAJOR__ >= 3
			if (k > 0 && (flags & (RTTI_MTH_CONSTRUCTOR|RTTI_MTH_STATIC)) == 0) {
			    k -= 1;
			    n = 1;
			}
#endif
			type->nParams = k;
			type->paramTypes = new RTTIType*[k];		
			k = 0;
			while (v->type->u.kmethod->arg_types[n] != NULL) { 
			    type->paramTypes[k++] = getType(v->type->u.kmethod->arg_types[n++]);
			}
			type->calculateFrameSize();
		    } else { 
			type->nParams = 0;
			type->paramTypes = NULL;
			type->frameSize = 0;
		    }
		    if (type->nParams == 0 && (flags & RTTI_MTH_CONSTRUCTOR) != 0) { 
			cls->defaultConstructor = (RTTIClassDescriptor::RTTIDefaultConstructor)type->methodAddress;
		    }
		    *mdp = md;
		    mdp = &md->next;
		}
	    }
	}
	*mdp = NULL;
	cls->buildClassDescriptor();
    }
}


bool RTTIBfdRepository::readBFD(bfd* abfd)
{
    asymbol **syms = NULL;
    long storage;

    if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
    {
	return false;
    }

    storage = bfd_get_symtab_upper_bound (abfd);
    if (storage < 0) { 
	bfd_fatal (bfd_get_filename (abfd));
    }

    if (storage) {
	syms = (asymbol **) xmalloc (storage);
    }
    int symcount = bfd_canonicalize_symtab (abfd, syms);
    if (symcount < 0) { 
	bfd_fatal (bfd_get_filename (abfd));
    }

    handle = read_debugging_info (abfd, syms, symcount);
    if (handle == NULL) { 
	return false;
    }
	
    debug_type** classes = debug_get_all_classes(handle);
    if (classes != NULL) {
	int i;
	for (i = 0; classes[i] != NULL; i++) {
	    loadClass(classes[i]);
	}
	for (i = 0; classes[i] != NULL; i++) {
	    readClass(classes[i]);
	}
    }
}

bool RTTIBfdRepository::loadBFD(bfd *abfd)
{
    char **matching;
    
    if (bfd_check_format_matches (abfd, bfd_object, &matching)) {
	return readBFD(abfd);
    }

    if (bfd_get_error() == bfd_error_file_ambiguously_recognized
	|| bfd_get_error() != bfd_error_file_not_recognized)
    {
	return false;
    }

    if (bfd_check_format_matches (abfd, bfd_core, &matching)) {
	return readBFD(abfd);
    }
    return false;
}


bool RTTIBfdRepository::load(char const* filePath)
{
    bfd *file, *arfile = (bfd *) NULL;
    
    file = bfd_openr (filePath, NULL);
    if (file == NULL) {
	return false;
    }
    
    if (bfd_check_format (file, bfd_archive) == true) {
	bfd *last_arfile = NULL;
	
	printf ("In archive %s:\n", bfd_get_filename (file));
	for (;;) {
	    bfd_set_error (bfd_error_no_error);
	    
	    arfile = bfd_openr_next_archived_file (file, arfile);
	    if (arfile == NULL) {
		if (bfd_get_error () != bfd_error_no_more_archived_files) { 
		    return false;
		}
	    }

	    loadBFD(arfile);

	    if (last_arfile != NULL) { 
		bfd_close (last_arfile);
	    }
	    last_arfile = arfile;
	}

	if (last_arfile != NULL) { 
	    bfd_close (last_arfile);
	} 
    } else { 
	loadBFD (file);
    }
    bfd_close (file);
}

RTTIBfdRepository::~RTTIBfdRepository()
{
    for (RTTIClassDescriptor* cls = classes; cls != NULL; cls = cls->next) { 
	delete cls;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -