Page 1 of 2

RAWBInfo crash after ACTION_INFO

Posted: Sun Mar 04, 2012 12:24 am
by chris
I'm having an odd problem with WB Information and my handler.
As far as I can tell, RAWBInfo calls Info(), which sends my handler an ACTION_INFO packet, with a lock in Arg1 and a pointer to an InfoData structure in Arg2. I return what I'm pretty sure is the expected information, however RAWBInfo is crashing after it receives it (error code 80000003 - which I believe is "unaligned access"). It does not appear to send any other packets.
The only clue I have is that if I disable RAWBInfo, the built-in WB Information requester shows garbage for the volume name (although displays the same name perfectly on the window titlebar).

As Workbench itself calls ACTION_INFO repeatedly and displays the correct volume name on WB, I fail to see what can be wrong in my handler. If I set id_VolumeNode to NULL WB just displays the device name and filesystem ID, so I am confident it is getting the name from that pointer and that my DOSList contains the correct data.

This is what it is putting in InfoData:

Code: Select all

struct InfoData *info;

if(packet->dp_Type == ACTION_INFO) 						info = (struct InfoData *)BADDR(packet->dp_Arg2);
else 		info = (struct InfoData *)BADDR(packet->dp_Arg1);
	
info->id_NumSoftErrors = 0;
info->id_UnitNumber = 0;
info->id_DiskState = ID_VALIDATED;
info->id_NumBlocks = 0;
info->id_NumBlocksUsed = 0;
info->id_BytesPerBlock = 1;
info->id_DiskType = fs_id;
info->id_VolumeNode = MKBADDR(doslist);
info->id_InUse = 0;
And here is the crashlog for RAWBInfo (hopefully one of the devs can tell me what it is trying to do at the point it crashes):

Code: Select all

Crash log for task "Information..."

Generated by GrimReaper 53.2
Crash occured in module RAWBInfo at address 0x6F57D438
Type of crash: DSI (Data Storage Interrupt) exception

Register dump:
GPR (General Purpose Registers):
   0: 00000039 55BFC8D0 00000000 0000180F 5700B9D0 55BFC8D8 00000001 8000000F 
   8: 8000000B 81A1D1D0 8000000A 20687474 00000001 00000000 00000000 00000000 
  16: 53910000 5390D03C 53910000 5390D03C 5C65FC25 542A290C 5B7CE010 00000001 
  24: 53910000 53910000 53910000 53910000 55BFCA00 546D1B34 5700B9D0 5741BC30 


FPR (Floating Point Registers, NaN = Not a Number):
   0:              nan              nan     1.39065e-309     2.72594e+197 
   4:    -1.45594e-232     -1.45993e+44       -8.85e-167    -2.03651e+245 
   8:     1.42125e+119    -2.17935e+110     2.03821e+149                0 
  12:                0                0                0                0 
  16:                0                0                0                0 
  20:                0     5.30499e-315                0                0 
  24:                0                0                0    -2.97403e+284 
  28:                0                0                0    -1.13339e+280 

FPSCR (Floating Point Status and Control Register): 0x82004000


SPRs (Special Purpose Registers):
           Machine State (msr) : 0x0002F030
                Condition (cr) : 0x44422024
      Instruction Pointer (ip) : 0x6F57D438
       Xtended Exception (xer) : 0x00000004
                   Count (ctr) : 0x01416208
                     Link (lr) : 0x6F57D3B8
            DSI Status (dsisr) : 0x00000000
            Data Address (dar) : 0x81A1D1D0



680x0 emulated registers:
DATA: 00000000 0000009A 00000000 00000000 00000000 00000000 00000000 00000000 
ADDR: 00000000 55939620 00000000 00000000 00000000 00000000 00000000 55BFC8C0 
FPU0:                0                0                0                0 
FPU4:                0                0                0                0 



Symbol info:
Instruction pointer 0x6F57D438 belongs to module "RAWBInfo" (HUNK/Kickstart)

Stack trace:
    module RAWBInfo at 0x6F57D438 (section 5 @ 0x14418)
    module RAWBInfo at 0x6F56B218 (section 5 @ 0x21F8)
    module RAWBInfo at 0x6F570DF4 (section 5 @ 0x7DD4)
    module RAWBInfo at 0x6F571270 (section 5 @ 0x8250)
    module LIBS:workbench.library at 0x6FF175F4 (section 5 @ 0x615D4)
    module LIBS:workbench.library at 0x6FEF2E54 (section 5 @ 0x3CE34)
    native kernel module dos.library.kmod+0x00022a0c
    native kernel module kernel+0x0003af48
    native kernel module kernel+0x0003afc8
    

PPC disassembly:
 6f57d430: 817e0004   lwz               r11,4(r30)
 6f57d434: 5569103a   rlwinm            r9,r11,2,0,29
*6f57d438: 88090000   lbz               r0,0(r9)
 6f57d43c: 2f800000   cmpwi             cr7,r0,0
 6f57d440: 41beff80   beq-              cr7,0x6F57D3C0

Re: RAWBInfo crash after ACTION_INFO

Posted: Sun Mar 04, 2012 5:37 am
by tonyw
The "8...3" is a general data error, it could be anything, but it boils down to an illegal access (non-existent address, etc). Look at the DAR (0x81A1D1D0), it looks OK here, but if it is 0xABADCAFE or 0xDEADBEEF, then you have tried to read unallocated or freed memory (for instance).

Since your handler does not appear in the stack trace, it has already returned from the call, so you must be returning RAWBInfo some crook data.
I would look at the line:
"info->id_VolumeNode = MKBADDR(doslist);" (It's the only address that could be illegal in the struct InfoData).

The address "doslist" should be that of a struct VolumeNode. Are you sure you are using the right variable name here? Perhaps you mean an item IN doslist? The MKBADDR macro doesn't do any type checking, of course.
Do you mean "info->id_VolumeNode = MKBADDR((struct VolumeNode *) something)" ?

Also, I think you should explicitly test for ACTION_DISK_INFO (unless you are testing for it somewhere else).

Re: RAWBInfo crash after ACTION_INFO

Posted: Sun Mar 04, 2012 5:47 pm
by chris
tonyw wrote:Since your handler does not appear in the stack trace, it has already returned from the call, so you must be returning RAWBInfo some crook data.
I would look at the line:
"info->id_VolumeNode = MKBADDR(doslist);" (It's the only address that could be illegal in the struct InfoData).

The address "doslist" should be that of a struct VolumeNode. Are you sure you are using the right variable name here? Perhaps you mean an item IN doslist? The MKBADDR macro doesn't do any type checking, of course.
Do you mean "info->id_VolumeNode = MKBADDR((struct VolumeNode *) something)" ?
doslist is a struct DosList *, which I believe is correct (I can't see a dedicated struct VolumeNode anywhere). The includes even mention DosList:

Code: Select all

    BPTR  id_VolumeNode;       /* BCPL pointer to volume node (see DosList) */
It is using the dol_volume structure in the union. Perhaps RAWBInfo is expecting a DosList with one of the other unions filled in, or a DeviceNode structure? That field is not very well defined, and even the Info() AutoDoc says not to rely on it containing what it says!
Also, I think you should explicitly test for ACTION_DISK_INFO (unless you are testing for it somewhere else).
I'm testing for it before this routine is called.

Re: RAWBInfo crash after ACTION_INFO

Posted: Tue Mar 06, 2012 12:31 am
by chris
I tried passing a DeviceNode instead but it still crashes in the same place.

Here is the contents of my DOSList:

Code: Select all

struct DosList *doslist;

		doslist = IDOS->AllocDosObjectTags(DOS_DOSLIST, ADO_Name, rarray[A_NAME], TAG_DONE); /* rarray is a ReadArgs array where A_NAME is NAME/K */
	doslist->dol_Type = DLT_VOLUME;
	doslist->dol_Task = devnode->dn_Task; /* struct MsgPort * */
	doslist->dol_Lock = 0; /* just added this */
	IDOS->DateStamp(&doslist->dol_misc.dol_volume.dol_VolumeDate); /* just added this */
	doslist->dol_misc.dol_volume.dol_LockList = 0;
	doslist->dol_misc.dol_volume.dol_DiskType = fs_id; /* 0x44415601 */

	IDOS->NonBlockingModifyDosEntry(doslist, NBM_ADDDOSENTRY, NULL, NULL);

Re: RAWBInfo crash after ACTION_INFO

Posted: Tue Mar 06, 2012 4:24 am
by colinw
At a quick glance, info->id_NumBlocks = 0;

This can't be zero, it will probably cause a div/0 error or some other sort of math catastrophe.
Must be at least 1.

Especially with; info->id_BytesPerBlock = 1;

Re: RAWBInfo crash after ACTION_INFO

Posted: Tue Mar 06, 2012 8:56 am
by salass00
@chris

This is the code that I use in XADFileSystem to generate the volume:

Code: Select all

ed = IDOS->ExamineObjectTags(EX_FileHandleInput, fs->file, TAG_END);
if (!ed) {
    DismountArchive(fs);
    return IDOS->IoErr();
}
fs->root->date = ed->Date;
if (FindVolumeNode(fs, ed->Name, &ed->Date)) {
    IDOS->FreeDosObject(DOS_EXAMINEDATA, ed);
    DismountArchive(fs);
    return ERROR_OBJECT_IN_USE;
} else {
    dbug(("AllocDosObjectTags\n"));
    fs->volume = IDOS->AllocDosObjectTags(DOS_DOSLIST,
        ADO_Type,   DLT_VOLUME,
        ADO_Name,   ed->Name,
        TAG_END);
    if (!fs->volume) {
        IDOS->FreeDosObject(DOS_EXAMINEDATA, ed);
        DismountArchive(fs);
        return ERROR_NO_FREE_STORE;
    }
    fs->volume->dl_VolumeDate = ed->Date;
    fs->volume->dl_FSPrivate = fs->device->dn_Name;
    IDOS->FreeDosObject(DOS_EXAMINEDATA, ed);
    AddDosEntry(fs, (struct DosList *)fs->volume);
}

fs->volume->dl_Port = fs->pkt_port;
fs->volume->dl_DiskType = ID_XAD_DISK;
fs->disktype = ID_XAD_DISK;

NotifyDiskChange(fs, IECLASS_DISKINSERTED);
The fs->volume variable is of type "struct DeviceList *".

Where AddDosEntry() is:

Code: Select all

static void AddDosEntry (struct DosList *dl) {
	while (!IDOS->NonBlockingModifyDosEntry(dl, NBM_ADDDOSENTRY, NULL, NULL)) {
		IDOS->Delay(5);
	}
}

Re: RAWBInfo crash after ACTION_INFO

Posted: Tue Mar 06, 2012 7:47 pm
by chris
@colinw

Tried that, no change. The Info() Autodoc warns that it could be 0 so I'd be a bit worried if RAWBInfo wasn't checking that.

@salass00

Changed my DosList to a DeviceList, but other than the code being neater it has made no difference.

What are you passing back in ACTION_INFO?

Re: RAWBInfo crash after ACTION_INFO

Posted: Tue Mar 06, 2012 8:50 pm
by salass00
@chris

The complete source code is in the archive I linked to above, but here are the relevant parts for the ACTION_DISK_INFO and ACTION_INFO packets implementation:

Code: Select all

case ACTION_DISK_INFO:
    pkt->dp_Res2 = DiskInfo(fs, BADDR(pkt->dp_Arg1));
    pkt->dp_Res1 = !pkt->dp_Res2 ? DOSTRUE : DOSFALSE;
    break;
case ACTION_INFO: {
    struct ExtFileLock *lock;
    lock = BADDR(pkt->dp_Arg1);
    if (lock && fs->volume != BADDR(lock->fl_Volume)) {
        pkt->dp_Res1 = DOSFALSE;
        pkt->dp_Res2 = ERROR_DEVICE_NOT_MOUNTED;
        break;
    }
    pkt->dp_Res2 = DiskInfo(fs, BADDR(pkt->dp_Arg2));
    pkt->dp_Res1 = !pkt->dp_Res2 ? DOSTRUE : DOSFALSE;
    break;
}

Code: Select all

#define BLOCKSHIFT 10
#define BLOCKSIZE 1024
#define BLOCKMASK 1023
#define SIZE2BLOCKS(s) (((s)>>BLOCKSHIFT)+((s&BLOCKMASK)?1:0))

int32 DiskInfo (struct FSGlobal *fs, struct InfoData *id) {
    struct UtilityIFace *IUtility = fs->util_interface;
    if (!id) {
        return ERROR_REQUIRED_ARG_MISSING;
    }
    IUtility->ClearMem(id, sizeof(*id));
    id->id_DiskState = ID_WRITE_PROTECTED;
    id->id_NumBlocks = id->id_NumBlocksUsed = SIZE2BLOCKS(fs->disksize);
    id->id_BytesPerBlock = BLOCKSIZE;
    id->id_DiskType = fs->disktype;
    id->id_VolumeNode = MKBADDR(fs->volume);
    id->id_InUse = fs->locklist ? DOSTRUE : DOSFALSE;
    return 0;
}
Nothing really special there, fs->disktype is set to 0x58414400 ('XAD\0').

Re: RAWBInfo crash after ACTION_INFO

Posted: Thu Mar 08, 2012 9:22 pm
by chris
salass00 wrote:@chris

The complete source code is in the archive I linked to above, but here are the relevant parts for the ACTION_DISK_INFO and ACTION_INFO packets implementation:
Nothing really special there, fs->disktype is set to 0x58414400 ('XAD\0').
Looks no different from what I'm doing. I think the only way I'm going to track this down is if one of the OS4 devs can tell me exactly what RAWBInfo is doing at the offset it is crashing at.

Re: RAWBInfo crash after ACTION_INFO

Posted: Fri Mar 23, 2012 10:05 am
by salass00
@chris
doslist = IDOS->AllocDosObjectTags(DOS_DOSLIST, ADO_Name, rarray[A_NAME], TAG_DONE);
Just wondering why you don't set ADO_Type here to DLT_VOLUME? Then you won't have to poke it into the structure later and if AllocDosObject() needs to do some specific initialisation for DLT_VOLUME then it will be able to do so.