📄 semihost.c
字号:
/* -*-C-*-
*
* $Revision: 1.27.2.25.18.15 $
* $Author: gevans $
* $Date: 2004/11/11 10:28:00 $
*
* OS.c - ARMulator III Operating System Interface.
*
* Copyright (c) 1999-2003 ARM Limited
* All Rights Reserved.
*/
#define MODEL_NAME OS
/*
* This file contains a model of ARM's Debug Monitors, including
* all the SWI's required to support the C library.
*/
/* needed to get EBADF=9 and EMFILE=24 from errno.h on HP/UX */
#define _POSIX_SOURCE 1
/* needed to get tempname() from stdio.h */
#define _XOPEN_SOURCE
/* Get the functional form of errno from erro.h on Solaris,
* to cope with AXD's threading/linkage. */
#define _REENTRANT
/* Include extra rdi-property */
#define CPUTIME_HI
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "toolconf.h"
#include "stringx.h" /* for StrDup */
#include "minperip.h"
#include "armul_hostif.h"
#include "armul_askrdi.h"
#include "armul_cnf.h" /* for ARMulCnf_Clock */
#include "armsignal.h"
#include "rdi_conf.h" /* for Dbg_Cnf_CPUSpeed */
#include "rdi_prop.h" /* for RDIProperty_SetAsNumeric */
#include "semihost.h"
#include "armul_propid.h" /* ARMul_RDIPropertyDesc */
#include "mini_simrdi_manager.h" /* for SIMABS awareness */
/* --- Debugging verbosity --- */
#ifndef NDEBUG
# if 1
# else
# define VERBOSE_RESET
# define VERBOSE_SYS_FILE
# define VERBOSE_SET_ENDIAN
# define VERBOSE_GetCS
# define VERBOSE_OS_INFO
# define VERBOSE_EXCEPTION
# define VERBOSE_CLI
# define VERBOSE_EVENTS
# define VERBOSE_CMDLINE
# define VERBOSE_DEMON_EXIT
# define VERBOSE_ANGEL_EVENTS
# define VERBOSE_INIT
# endif
#endif
/*# define VERBOSE_SYS_FILE*/
/* Design decisions */
#define CMDLINE_LENGTH_EXCLUDES_NULL
static RDI_InfoProc OS_HandleUnkRDI;
static GenericCallbackFunc OS_HandleException;
static GenericCallbackFunc OS_HandleEvent;
#ifndef __STDC__
#define remove(s) unlink(s)
#endif
#ifndef NO_DEMON
#define CURRENTMODE RDIMode_Curr
/*
* Mode Constants - obsolete names
*/
#define USER32MODE ARM_M_USER32
#define FIQ32MODE ARM_M_FIQ32
#define IRQ32MODE ARM_M_IRQ32
#define SVC32MODE ARM_M_SVC32
#define ABORT32MODE ARM_M_ABORT32
#define UNDEF32MODE ARM_M_UNDEF32
#define SYSTEM32MODE ARM_M_SYSTEM32
#endif
/***************************************************************************\
* OS_MoveBackOneInstruction *
\***************************************************************************/
static void OS_MoveBackOneInstruction(RDI_ModuleDesc* coredesc, ARMword pc, ARMword mode)
/* should be in ARMulif, we assume that CPSR is the appropriate
mode, if the core has already swapped states then this will
not work */
{
ARMulif_SetReg(coredesc,
mode, 15,
pc - ( ( ARMulif_GetCPSR(coredesc) & (1<<5) ) /* is thumb/arm */
? 4 : 8 )
);
}
/***************************************************************************\
* (demon) SWI numbers + 0x100 *
\***************************************************************************/
#define SWI_WriteC 0x100 + 0x0
#define SWI_Write0 0x100 + 0x2
#define SWI_ReadC 0x100 + 0x4
#define SWI_CLI 0x100 + 0x5
#define SWI_GetEnv 0x100 + 0x10
#define SWI_Exit 0x100 + 0x11
#define SWI_EnterOS 0x100 + 0x16
#define SWI_WriteHex 0x100 + 0x17
#define SWI_GetErrno 0x100 + 0x60
#define SWI_Clock 0x100 + 0x61
#define SWI_Time 0x100 + 0x63
#define SWI_Remove 0x100 + 0x64
#define SWI_Rename 0x100 + 0x65
#define SWI_Open 0x100 + 0x66
#define SWI_Close 0x100 + 0x68
#define SWI_Write 0x100 + 0x69
#define SWI_Read 0x100 + 0x6a
#define SWI_Seek 0x100 + 0x6b
#define SWI_Flen 0x100 + 0x6c
#define SWI_IsTTY 0x100 + 0x6e
#define SWI_TmpNam 0x100 + 0x6f
#define SWI_InstallHandler 0x100 + 0x70
#define SWI_GenerateError 0x100 + 0x71
/***************************************************************************\
* OS private Information *
\***************************************************************************/
/* Configuration-names */
#define ARMulCnf_AddrSuperStack "ADDRSUPERSTACK"
#define ARMulCnf_AddrAbortStack "ADDRABORTSTACK"
#define ARMulCnf_AddrUndefStack "ADDRUNDEFSTACK"
#define ARMulCnf_AddrIRQStack "ADDRIRQSTACK"
#define ARMulCnf_AddrFIQStack "ADDRFIQSTACK"
#define ARMulCnf_AddrUserStack "ADDRUSERSTACK"
#define ARMulCnf_AddrSoftVectors "ADDRSOFTVECTORS"
#define ARMulCnf_AddrCmdLine "ADDRCMDLINE"
#define ARMulCnf_AddrsOfHandlers "ADDRSOFHANDLERS"
#define ARMulCnf_SoftVectorCode "SOFTVECTORCODE"
#define ARMulCnf_AngelSWIARM "ANGELSWIARM"
#define ARMulCnf_AngelSWIThumb "ANGELSWITHUMB"
#define ARMulCnf_HeapBase "HEAPBASE"
#define ARMulCnf_HeapLimit "HEAPLIMIT"
#define ARMulCnf_StackBase "STACKBASE"
#define ARMulCnf_StackLimit "STACKLIMIT"
#define ARMulCnf_Angel "ANGEL"
#define ARMulCnf_Demon "DEMON"
/***************************************************************************\
* Define the initial layout of memory *
\***************************************************************************/
#define DEMON_ADDRSUPERSTACK 0xA00L /* supervisor stack space */
#define DEMON_ADDRABORTSTACK 0x800L /* abort stack space */
#define DEMON_ADDRUNDEFSTACK 0x700L /* undef stack space */
#define DEMON_ADDRIRQSTACK 0x500L /* IRQ stack space */
#define DEMON_ADDRFIQSTACK 0x400L /* FIQ stack space */
#define DEMON_ADDRUSERSTACK 0x80000L /* default user stack start */
#define DEMON_ADDRCMDLINE 0xf00L /* command line is here after a SWI GetEnv */
/* Sizes of shamefully fixed-size arrays. */
#define UNIQUETEMPS 256
#define BUFFERSIZE 4096
#define NONHANDLE -1
#ifndef FOPEN_MAX
#define FOPEN_MAX 64
#endif
BEGIN_STATE_DECL(OS)
ARMword CycleStarted;
ARMword InstStarted;
ARMword ErrorNo;
char *CommandLine ;
FILE *FileTable[FOPEN_MAX];
char FileFlags[FOPEN_MAX];
unsigned FileCount[FOPEN_MAX];
char OpenMode[FOPEN_MAX];
char *tempnames[UNIQUETEMPS];
bool sh_Bigend32;
bool Set_Endian;
bool_int os_verbose;
uint32 semihostingvector,
semihostingstate; /* from debugger */
unsigned AngelEnabled ;
unsigned DemonEnabled ;
bool ExitSwisEnabled;
unsigned os_HaltOnUnknownAngelSwi; /* bool */
uint32 os_CPUSpeed, os_BusSpeed;
ARMword usersp; /* user stack pointer */
ARMword cmdlineaddr; /* where the command line is placed */
ARMword AngelSWIARM;
ARMword AngelSWIThumb;
ARMword heap_base,heap_limit;
ARMword stack_base,stack_limit;
struct {
struct {
ARMword svc,abt,undef;
ARMword irq,fiq,user;
} sp; /* Stack pointers */
ARMword soft_vectors; /* where the soft vectors start */
ARMword cmd_line; /* where the command line is placed */
ARMword handlers; /* addr/workspace for handlers */
ARMword soft_vec_code; /* default handlers */
} map;
uint32 vector_catch;
FILE *os_file_log;
bool bStop_Received;
/*
* Saved state for resuming sys_read
*/
bool bResume_Read;
char saved_buffer[BUFFERSIZE];
unsigned saved_size, saved_type;
ARMword saved_addr;
bool_int os_bUseRealTime;
ARMword os_FakeTimeFrom; /* Independent of the above - affects TIME */
/*
* SIMABS awareness:
*
* We need for semihosting exit to return RDIError_TargetStopped if we hit
* the semihosting stop vector. Otherwise there is no way for a step call
* to figure out that it has stopped.
*/
SimRdiProcVec* simrdiprocvec; /* non-null if running under a SimRdi_Manager */
Advert_ID advert;
Advert_ID advert_regs;
Advert_ID os_ad_to_destroy;
/*
* Build a line here for tracing or comparison.
*/
# define LINE_LENGTH 128
char linebuf[LINE_LENGTH];
unsigned nchars_in_linebuf;
TracerPrintfCallback os_TracerPrintf;
bool_int os_Trace_OutPut;
#ifdef VERBOSE_SYS_FILE
bool verbose_sys_file;
#endif
END_STATE_DECL(OS)
static Register_Definition semihost_reg_defs[] = {
#define S(symbol,buttonname,readonlyQ) \
{ 4, EECHGCASE_DOWN, TYPE_UNSIGNED_LONG, "@semihost_" symbol, buttonname, readonlyQ, 0 }
S("state", "Semihosting_State ", 0), /* if order changes _must_ change OS_SimReg() */
S("ARM_SWI", "ARM_SWI ", 0), /* if order changes _must_ change OS_SimReg() */
S("Thumb_SWI", "Thumb_SWI ", 0), /* if order changes _must_ change OS_SimReg() */
/* SYS_ERRNO */
S("errno", "Errno ", 0), /* if order changes _must_ change OS_SimReg() */
/* SYS_HEAPINFO */
S("heap_base", "Heap_Base ", 0), /* if order changes _must_ change OS_SimReg() */
S("heap_limit", "Heap_Limit ", 0), /* if order changes _must_ change OS_SimReg() */
S("stack_base", "Stack_Base ", 0), /* if order changes _must_ change OS_SimReg() */
S("stack_limit", "Stack_Limit ", 0), /* if order changes _must_ change OS_SimReg() */
S("vector_catch", "Vector_Catch ", 0), /* if order changes _must_ change OS_SimReg() */
/* SWI_GetEnv */
S("addr_cmd_line", "Addr_Cmd_Line ", 0), /* if order changes _must_ change OS_SimReg() */
S("addr_user_stack", "Addr_User_Stack ", 0), /* if order changes _must_ change OS_SimReg() */
/* Goodies */
S("number_of_files_open", "Number_Of_Files_Open ", 1), /* if order changes _must_ change OS_SimReg() */
#undef S
};
static RDI_Error
call_RDIInfo(OSState* osstate, unsigned type, ARMword *arg1, ARMword *arg2)
{
return osstate->coredesc.rdi->info(osstate->coredesc.handle, type, arg1, arg2);
}
static SimabsRegisterAccess OS_SimReg;
static SIM_ERR
OS_SimReg( void* handle, bool_int reg_read,
uint32 reg_num,
REGVAL* regval, uint16 size )
{
OSState* osstate = (OSState*)handle;
UNUSEDARG(size); /* should always be 4! */
switch(reg_num)
{
#define S(NUMBER, statevar) \
case NUMBER: if(reg_read) { regval->reg32 = osstate->statevar; } else { osstate->statevar = regval->reg32; }
#define RDIS(NUMBER, statevar, SETINFO) case NUMBER: \
if (reg_read) { regval->reg32 = osstate->statevar; } \
else { ARMword temp = 0; call_RDIInfo(osstate, SETINFO, ®val->reg32, &temp ); }
S(0, semihostingstate); break; /* should normalise to 0 or 1? */
RDIS(1, AngelSWIARM, RDISemiHosting_SetARMSWI ); break;
RDIS(2, AngelSWIThumb, RDISemiHosting_SetThumbSWI); break;
S(3, ErrorNo ); break;
S(4, heap_base ); break;
S(5, heap_limit ); break;
S(6, stack_base ); break;
S(7, stack_limit); break;
RDIS(8, vector_catch, RDISemiHosting_SetVector ); break;
S(9, cmdlineaddr); break;
S(10, usersp ); break;
case 11: /* number of files open */
{
unsigned i;
unsigned count = 0;
for (i=0; i<FOPEN_MAX; ++i)
{
if (osstate->FileTable[i] != NULL)
{
++count;
}
}
regval->reg32 = count;
}
break;
default:
return SIM_REGISTER_ACCESS;
}
return SIM_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -