Package: release.debian.org Severity: normal Tags: stretch User: release.debian....@packages.debian.org Usertags: pu
dosbox is broken in the default setting on a number of systems/DOS binaries (see #857341). This got fixed in unstable back in September, but the patch is also needed in stretch. Apart from debian/changelog, the debdiff the only change applied to the package in unstable since the stretch release. I've verified that with updated packages "Syndicate" now works fine. Cheers, Moritz
diff -Nru dosbox-0.74/debian/changelog dosbox-0.74/debian/changelog --- dosbox-0.74/debian/changelog 2015-10-13 16:55:00.000000000 +0200 +++ dosbox-0.74/debian/changelog 2018-05-21 22:55:46.000000000 +0200 @@ -1,3 +1,10 @@ +dosbox (0.74-4.2+deb9u1) stretch; urgency=medium + + * Non-maintainer upload: + * Fix crashes with core=dynamic (Closes: #857341) + + -- Moritz Mühlenhoff <j...@debian.org> Mon, 21 May 2018 22:55:46 +0200 + dosbox (0.74-4.2) unstable; urgency=medium * non-maintainer upload diff -Nru dosbox-0.74/debian/patches/series dosbox-0.74/debian/patches/series --- dosbox-0.74/debian/patches/series 2015-06-17 20:28:00.000000000 +0200 +++ dosbox-0.74/debian/patches/series 2018-05-21 22:55:31.000000000 +0200 @@ -3,3 +3,4 @@ fix-ftbfs-format-security.patch wine-move-z-mount-svn3736.patch wine-style-namemangling-svn3742.patch +update-64bit-recompiler.patch diff -Nru dosbox-0.74/debian/patches/update-64bit-recompiler.patch dosbox-0.74/debian/patches/update-64bit-recompiler.patch --- dosbox-0.74/debian/patches/update-64bit-recompiler.patch 1970-01-01 01:00:00.000000000 +0100 +++ dosbox-0.74/debian/patches/update-64bit-recompiler.patch 2018-05-21 22:55:22.000000000 +0200 @@ -0,0 +1,437 @@ +From: gulikoza +Bug-Debian: https://bugs.debian.org/857341 +Description: Update 64bit dynamic recompiler to fix several bugs + This adds support for absolute 64bit addressing and fixes the + "Unhandled memory reference" crash. This comes from upstream SVN + r3951, and includes related patches r3674 and r3894. This patch also + contains an LLVM compile fix (r3990). +Index: dosbox-0.74/src/cpu/core_dynrec/risc_x64.h +=================================================================== +--- dosbox-0.74.orig/src/cpu/core_dynrec/risc_x64.h ++++ dosbox-0.74/src/cpu/core_dynrec/risc_x64.h +@@ -83,36 +83,106 @@ static void gen_mov_regs(HostReg reg_dst + cache_addb(0xc0+(reg_dst<<3)+reg_src); + } + ++// move a 64bit constant value into a full register ++static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) { ++ cache_addb(0x48); ++ cache_addb(0xb8+dest_reg); // mov dest_reg,imm ++ cache_addq(imm); ++} + +-static INLINE void gen_memaddr(HostReg reg,void* data) { +- Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+5); +- if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { ++ ++// This function generates an instruction with register addressing and a memory location ++static INLINE void gen_reg_memaddr(HostReg reg,void* data,Bit8u op,Bit8u prefix=0) { ++ Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+(prefix?7:6)); ++// if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { //clang messes itself up on this... ++ if ( (diff>>63) == (diff>>31) ) { //signed bit extend, test to see if value fits in a Bit32s ++ // mov reg,[rip+diff] (or similar, depending on the op) to fetch *data ++ if(prefix) cache_addb(prefix); ++ cache_addb(op); + cache_addb(0x05+(reg<<3)); + // RIP-relative addressing is offset after the instruction + cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); + } else if ((Bit64u)data<0x100000000LL) { ++ // mov reg,[data] (or similar, depending on the op) when absolute address of data is <4GB ++ if(prefix) cache_addb(prefix); ++ cache_addb(op); + cache_addw(0x2504+(reg<<3)); + cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); + } else { +- E_Exit("DRC64:Unhandled memory reference"); ++ // load 64-bit data into tmp_reg and do mov reg,[tmp_reg] (or similar, depending on the op) ++ HostReg tmp_reg = HOST_EAX; ++ if(reg == HOST_EAX) tmp_reg = HOST_ECX; ++ ++ cache_addb(0x50+tmp_reg); // push rax/rcx ++ gen_mov_reg_qword(tmp_reg,(Bit64u)data); ++ ++ if(prefix) cache_addb(prefix); ++ cache_addb(op); ++ cache_addb(tmp_reg+(reg<<3)); ++ ++ cache_addb(0x58+tmp_reg); // pop rax/rcx + } + } + ++// Same as above, but with immediate addressing and a memory location ++static INLINE void gen_memaddr(Bitu modreg,void* data,Bitu off,Bitu imm,Bit8u op,Bit8u prefix=0) { ++ Bit64s diff = (Bit64s)data-((Bit64s)cache.pos+off+(prefix?7:6)); ++// if ((diff<0x80000000LL) && (diff>-0x80000000LL)) { ++ if ( (diff>>63) == (diff>>31) ) { ++ // RIP-relative addressing is offset after the instruction ++ if(prefix) cache_addb(prefix); ++ cache_addw(op+((modreg+1)<<8)); ++ cache_addd((Bit32u)(((Bit64u)diff)&0xffffffffLL)); ++ ++ switch(off) { ++ case 1: cache_addb(((Bit8u)imm&0xff)); break; ++ case 2: cache_addw(((Bit16u)imm&0xffff)); break; ++ case 4: cache_addd(((Bit32u)imm&0xffffffff)); break; ++ } ++ ++ } else if ((Bit64u)data<0x100000000LL) { ++ if(prefix) cache_addb(prefix); ++ cache_addw(op+(modreg<<8)); ++ cache_addb(0x25); ++ cache_addd((Bit32u)(((Bit64u)data)&0xffffffffLL)); ++ ++ switch(off) { ++ case 1: cache_addb(((Bit8u)imm&0xff)); break; ++ case 2: cache_addw(((Bit16u)imm&0xffff)); break; ++ case 4: cache_addd(((Bit32u)imm&0xffffffff)); break; ++ } ++ ++ } else { ++ HostReg tmp_reg = HOST_EAX; ++ ++ cache_addb(0x50+tmp_reg); // push rax ++ gen_mov_reg_qword(tmp_reg,(Bit64u)data); ++ ++ if(prefix) cache_addb(prefix); ++ cache_addw(op+((modreg-4+tmp_reg)<<8)); ++ ++ switch(off) { ++ case 1: cache_addb(((Bit8u)imm&0xff)); break; ++ case 2: cache_addw(((Bit16u)imm&0xffff)); break; ++ case 4: cache_addd(((Bit32u)imm&0xffffffff)); break; ++ } ++ ++ cache_addb(0x58+tmp_reg); // pop rax ++ } ++} + + // move a 32bit (dword==true) or 16bit (dword==false) value from memory into dest_reg + // 16bit moves may destroy the upper 16bit of the destination register +-static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword) { +- if (!dword) cache_addb(0x66); +- cache_addb(0x8b); // mov reg,[data] +- gen_memaddr(dest_reg,data); ++static void gen_mov_word_to_reg(HostReg dest_reg,void* data,bool dword,Bit8u prefix=0) { ++ if (!dword) gen_reg_memaddr(dest_reg,data,0xb7,0x0f); // movzx reg,[data] - zero extend data, fixes LLVM compile where the called function does not extend the parameters ++ else gen_reg_memaddr(dest_reg,data,0x8b,prefix); // mov reg,[data] + } + + // move a 16bit constant value into dest_reg + // the upper 16bit of the destination register may be destroyed + static void gen_mov_word_to_reg_imm(HostReg dest_reg,Bit16u imm) { +- cache_addb(0x66); + cache_addb(0xb8+dest_reg); // mov reg,imm +- cache_addw(imm); ++ cache_addd((Bit32u)imm); + } + + // move a 32bit constant value into dest_reg +@@ -122,10 +192,8 @@ static void gen_mov_dword_to_reg_imm(Hos + } + + // move 32bit (dword==true) or 16bit (dword==false) of a register into memory +-static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword) { +- if (!dword) cache_addb(0x66); +- cache_addb(0x89); // mov [data],reg +- gen_memaddr(src_reg,dest); ++static void gen_mov_word_from_reg(HostReg src_reg,void* dest,bool dword,Bit8u prefix=0) { ++ gen_reg_memaddr(src_reg,dest,0x89,(dword?prefix:0x66)); // mov [data],reg + } + + // move an 8bit value from memory into dest_reg +@@ -133,8 +201,7 @@ static void gen_mov_word_from_reg(HostRe + // this function does not use FC_OP1/FC_OP2 as dest_reg as these + // registers might not be directly byte-accessible on some architectures + static void gen_mov_byte_to_reg_low(HostReg dest_reg,void* data) { +- cache_addb(0x8a); // mov reg,[data] +- gen_memaddr(dest_reg,data); ++ gen_reg_memaddr(dest_reg,data,0xb6,0x0f); // movzx reg,[data] + } + + // move an 8bit value from memory into dest_reg +@@ -142,9 +209,7 @@ static void gen_mov_byte_to_reg_low(Host + // this function can use FC_OP1/FC_OP2 as dest_reg which are + // not directly byte-accessible on some architectures + static void gen_mov_byte_to_reg_low_canuseword(HostReg dest_reg,void* data) { +- cache_addb(0x66); +- cache_addb(0x8b); // mov reg,[data] +- gen_memaddr(dest_reg,data); ++ gen_reg_memaddr(dest_reg,data,0xb6,0x0f); // movzx reg,[data] + } + + // move an 8bit constant value into dest_reg +@@ -152,8 +217,8 @@ static void gen_mov_byte_to_reg_low_canu + // this function does not use FC_OP1/FC_OP2 as dest_reg as these + // registers might not be directly byte-accessible on some architectures + static void gen_mov_byte_to_reg_low_imm(HostReg dest_reg,Bit8u imm) { +- cache_addb(0xb0+dest_reg); // mov reg,imm +- cache_addb(imm); ++ cache_addb(0xb8+dest_reg); // mov reg,imm ++ cache_addd((Bit32u)imm); + } + + // move an 8bit constant value into dest_reg +@@ -161,15 +226,13 @@ static void gen_mov_byte_to_reg_low_imm( + // this function can use FC_OP1/FC_OP2 as dest_reg which are + // not directly byte-accessible on some architectures + static void gen_mov_byte_to_reg_low_imm_canuseword(HostReg dest_reg,Bit8u imm) { +- cache_addb(0x66); + cache_addb(0xb8+dest_reg); // mov reg,imm +- cache_addw(imm); ++ cache_addd((Bit32u)imm); + } + + // move the lowest 8bit of a register into memory + static void gen_mov_byte_from_reg_low(HostReg src_reg,void* dest) { +- cache_addb(0x88); // mov [data],reg +- gen_memaddr(src_reg,dest); ++ gen_reg_memaddr(src_reg,dest,0x88); // mov byte [data],reg + } + + +@@ -192,8 +255,7 @@ static void gen_extend_word(bool sign,Ho + + // add a 32bit value from memory to a full register + static void gen_add(HostReg reg,void* op) { +- cache_addb(0x03); // add reg,[data] +- gen_memaddr(reg,op); ++ gen_reg_memaddr(reg,op,0x03); // add reg,[data] + } + + // add a 32bit constant value to a full register +@@ -212,33 +274,20 @@ static void gen_and_imm(HostReg reg,Bit3 + + // move a 32bit constant value into memory + static void gen_mov_direct_dword(void* dest,Bit32u imm) { +- cache_addw(0x04c7); // mov [data],imm +- cache_addb(0x25); +- cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); +- cache_addd(imm); ++ gen_memaddr(0x4,dest,4,imm,0xc7); // mov [data],imm + } + +-// move a 64bit constant value into a full register +-static void gen_mov_reg_qword(HostReg dest_reg,Bit64u imm) { +- cache_addb(0x48); +- cache_addb(0xb8+dest_reg); // mov dest_reg,imm +- cache_addq(imm); +-} + + // move an address into memory + static void INLINE gen_mov_direct_ptr(void* dest,DRC_PTR_SIZE_IM imm) { + gen_mov_reg_qword(HOST_EAX,imm); +- cache_addb(0x48); +- gen_mov_word_from_reg(HOST_EAX,dest,true); ++ gen_mov_word_from_reg(HOST_EAX,dest,true,0x48); // 0x48 prefixes full 64-bit mov + } + + + // add an 8bit constant value to a memory value + static void gen_add_direct_byte(void* dest,Bit8s imm) { +- cache_addw(0x0483); // add [data],imm +- cache_addb(0x25); +- cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); +- cache_addb(imm); ++ gen_memaddr(0x4,dest,1,imm,0x83); // add [data],imm + } + + // add a 32bit (dword==true) or 16bit (dword==false) constant value to a memory value +@@ -247,20 +296,12 @@ static void gen_add_direct_word(void* de + gen_add_direct_byte(dest,(Bit8s)imm); + return; + } +- if (!dword) cache_addb(0x66); +- cache_addw(0x0481); // add [data],imm +- cache_addb(0x25); +- cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); +- if (dword) cache_addd((Bit32u)imm); +- else cache_addw((Bit16u)imm); ++ gen_memaddr(0x4,dest,(dword?4:2),imm,0x81,(dword?0:0x66)); // add [data],imm + } + + // subtract an 8bit constant value from a memory value + static void gen_sub_direct_byte(void* dest,Bit8s imm) { +- cache_addw(0x2c83); // sub [data],imm +- cache_addb(0x25); +- cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); +- cache_addb(imm); ++ gen_memaddr(0x2c,dest,1,imm,0x83); + } + + // subtract a 32bit (dword==true) or 16bit (dword==false) constant value from a memory value +@@ -269,12 +310,7 @@ static void gen_sub_direct_word(void* de + gen_sub_direct_byte(dest,(Bit8s)imm); + return; + } +- if (!dword) cache_addb(0x66); +- cache_addw(0x2c81); // sub [data],imm +- cache_addb(0x25); +- cache_addd((Bit32u)(((Bit64u)dest)&0xffffffffLL)); +- if (dword) cache_addd((Bit32u)imm); +- else cache_addw((Bit16u)imm); ++ gen_memaddr(0x2c,dest,(dword?4:2),imm,0x81,(dword?0:0x66)); // sub [data],imm + } + + +@@ -324,10 +360,18 @@ static INLINE void gen_lea(HostReg dest_ + + // generate a call to a parameterless function + static void INLINE gen_call_function_raw(void * func) { ++ cache_addb(0x48); ++ cache_addw(0xec83); ++ cache_addb(0x08); // sub rsp,0x08 (align stack to 16 byte boundary) ++ + cache_addb(0x48); + cache_addb(0xb8); // mov reg,imm64 + cache_addq((Bit64u)func); + cache_addw(0xd0ff); ++ ++ cache_addb(0x48); ++ cache_addw(0xc483); ++ cache_addb(0x08); // add rsp,0x08 (reset alignment) + } + + // generate a call to a function with paramcount parameters +@@ -350,9 +394,13 @@ static Bit64u INLINE gen_call_function_s + cache_addw(0xc483); // add rsp,0x08 + cache_addb(0x08); + ++ // stack is 16 byte aligned now ++ ++ + cache_addb(0x50); // push rax (==old rsp) + +- Bit64u proc_addr=(Bit64u)cache.pos; ++ // returned address relates to where the address is stored in gen_call_function_raw ++ Bit64u proc_addr=(Bit64u)cache.pos-4; + + // Do the actual call to the procedure + cache_addb(0x48); +@@ -479,12 +527,10 @@ static void INLINE gen_load_param_mem(Bi + break; + #if defined (_MSC_VER) + case 2: // mov r8,[mem] +- cache_addb(0x49); +- gen_mov_word_to_reg(0,(void*)mem,true); ++ gen_mov_word_to_reg(0,(void*)mem,true,0x49); // 0x49, use x64 rX regs + break; + case 3: // mov r9,[mem] +- cache_addb(0x49); +- gen_mov_word_to_reg(1,(void*)mem,true); ++ gen_mov_word_to_reg(1,(void*)mem,true,0x49); // 0x49, use x64 rX regs + break; + #else + case 2: // mov rdx,[mem] +@@ -596,6 +642,8 @@ static void gen_return_function(void) { + #ifdef DRC_FLAGS_INVALIDATION + // called when a call to a function can be replaced by a + // call to a simpler function ++// check gen_call_function_raw and gen_call_function_setup ++// for the targeted code + static void gen_fill_function_ptr(Bit8u * pos,void* fct_ptr,Bitu flags_type) { + #ifdef DRC_FLAGS_INVALIDATION_DCODE + // try to avoid function calls but rather directly fill in code +@@ -604,36 +652,46 @@ static void gen_fill_function_ptr(Bit8u + case t_ADDw: + case t_ADDd: + *(Bit32u*)(pos+0)=0xf001f889; // mov eax,edi; add eax,esi +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_ORb: + case t_ORw: + case t_ORd: + *(Bit32u*)(pos+0)=0xf009f889; // mov eax,edi; or eax,esi +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_ANDb: + case t_ANDw: + case t_ANDd: + *(Bit32u*)(pos+0)=0xf021f889; // mov eax,edi; and eax,esi +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_SUBb: + case t_SUBw: + case t_SUBd: + *(Bit32u*)(pos+0)=0xf029f889; // mov eax,edi; sub eax,esi +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_XORb: + case t_XORw: + case t_XORd: + *(Bit32u*)(pos+0)=0xf031f889; // mov eax,edi; xor eax,esi +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_CMPb: + case t_CMPw: +@@ -641,37 +699,45 @@ static void gen_fill_function_ptr(Bit8u + case t_TESTb: + case t_TESTw: + case t_TESTd: +- *(Bit32u*)(pos+0)=0x90900aeb; // skip ++ *(Bit32u*)(pos+0)=0x909012eb; // skip + *(Bit32u*)(pos+4)=0x90909090; + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_INCb: + case t_INCw: + case t_INCd: + *(Bit32u*)(pos+0)=0xc0fff889; // mov eax,edi; inc eax +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_DECb: + case t_DECw: + case t_DECd: + *(Bit32u*)(pos+0)=0xc8fff889; // mov eax,edi; dec eax +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + case t_NEGb: + case t_NEGw: + case t_NEGd: + *(Bit32u*)(pos+0)=0xd8f7f889; // mov eax,edi; neg eax +- *(Bit32u*)(pos+4)=0x909006eb; // skip ++ *(Bit32u*)(pos+4)=0x90900eeb; // skip + *(Bit32u*)(pos+8)=0x90909090; ++ *(Bit32u*)(pos+12)=0x90909090; ++ *(Bit32u*)(pos+16)=0x90909090; + break; + default: +- *(Bit64u*)(pos+2)=(Bit64u)fct_ptr; // fill function pointer ++ *(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer + break; + } + #else +- *(Bit64u*)(pos+2)=(Bit64u)fct_ptr; ++ *(Bit64u*)(pos+6)=(Bit64u)fct_ptr; // fill function pointer + #endif + } + #endif